From 556e775ccb8a5cfd1ce706c2968bfa296563a2a0 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:24:19 -0800 Subject: [PATCH 01/14] chore(main): release 2.35.1-SNAPSHOT (#2436) 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 | 2 +- storage-shared-benchmarking/pom.xml | 4 ++-- versions.txt | 14 +++++++------- 12 files changed, 40 insertions(+), 40 deletions(-) diff --git a/gapic-google-cloud-storage-v2/pom.xml b/gapic-google-cloud-storage-v2/pom.xml index a53e6168d..d02b72dd1 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.35.0-alpha + 2.35.1-alpha-SNAPSHOT gapic-google-cloud-storage-v2 GRPC library for gapic-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.35.0 + 2.35.1-SNAPSHOT diff --git a/google-cloud-storage-bom/pom.xml b/google-cloud-storage-bom/pom.xml index fa4b7c464..bc0311201 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.35.0 + 2.35.1-SNAPSHOT pom com.google.cloud @@ -69,37 +69,37 @@ com.google.cloud google-cloud-storage - 2.35.0 + 2.35.1-SNAPSHOT com.google.api.grpc gapic-google-cloud-storage-v2 - 2.35.0-alpha + 2.35.1-alpha-SNAPSHOT com.google.api.grpc grpc-google-cloud-storage-v2 - 2.35.0-alpha + 2.35.1-alpha-SNAPSHOT com.google.api.grpc proto-google-cloud-storage-v2 - 2.35.0-alpha + 2.35.1-alpha-SNAPSHOT com.google.cloud google-cloud-storage-control - 2.35.0-alpha + 2.35.1-alpha-SNAPSHOT com.google.api.grpc grpc-google-cloud-storage-control-v2 - 2.35.0-alpha + 2.35.1-alpha-SNAPSHOT com.google.api.grpc proto-google-cloud-storage-control-v2 - 2.35.0-alpha + 2.35.1-alpha-SNAPSHOT diff --git a/google-cloud-storage-control/pom.xml b/google-cloud-storage-control/pom.xml index 5024de8d9..747b2b3d7 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.35.0-alpha + 2.35.1-alpha-SNAPSHOT google-cloud-storage-control GRPC library for google-cloud-storage-control com.google.cloud google-cloud-storage-parent - 2.35.0 + 2.35.1-SNAPSHOT diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml index 336e389c6..a7138c4b6 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -2,7 +2,7 @@ 4.0.0 google-cloud-storage - 2.35.0 + 2.35.1-SNAPSHOT jar Google Cloud Storage https://github.com/googleapis/java-storage @@ -12,7 +12,7 @@ com.google.cloud google-cloud-storage-parent - 2.35.0 + 2.35.1-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 4bbc8443e..1b9b70b4e 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.35.0-alpha + 2.35.1-alpha-SNAPSHOT grpc-google-cloud-storage-control-v2 GRPC library for google-cloud-storage com.google.cloud google-cloud-storage-parent - 2.35.0 + 2.35.1-SNAPSHOT diff --git a/grpc-google-cloud-storage-v2/pom.xml b/grpc-google-cloud-storage-v2/pom.xml index 3f1e01f20..a8f618376 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.35.0-alpha + 2.35.1-alpha-SNAPSHOT grpc-google-cloud-storage-v2 GRPC library for grpc-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.35.0 + 2.35.1-SNAPSHOT diff --git a/pom.xml b/pom.xml index b0052f5ec..3d04204c7 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-storage-parent pom - 2.35.0 + 2.35.1-SNAPSHOT Storage Parent https://github.com/googleapis/java-storage @@ -76,7 +76,7 @@ com.google.cloud google-cloud-storage - 2.35.0 + 2.35.1-SNAPSHOT com.google.apis @@ -117,32 +117,32 @@ com.google.api.grpc proto-google-cloud-storage-v2 - 2.35.0-alpha + 2.35.1-alpha-SNAPSHOT com.google.api.grpc grpc-google-cloud-storage-v2 - 2.35.0-alpha + 2.35.1-alpha-SNAPSHOT com.google.api.grpc gapic-google-cloud-storage-v2 - 2.35.0-alpha + 2.35.1-alpha-SNAPSHOT com.google.api.grpc grpc-google-cloud-storage-control-v2 - 2.35.0-alpha + 2.35.1-alpha-SNAPSHOT com.google.api.grpc proto-google-cloud-storage-control-v2 - 2.35.0-alpha + 2.35.1-alpha-SNAPSHOT com.google.cloud google-cloud-storage-control - 2.35.0-alpha + 2.35.1-alpha-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 5290cbda1..f028d71dd 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.35.0-alpha + 2.35.1-alpha-SNAPSHOT proto-google-cloud-storage-control-v2 Proto library for proto-google-cloud-storage-control-v2 com.google.cloud google-cloud-storage-parent - 2.35.0 + 2.35.1-SNAPSHOT diff --git a/proto-google-cloud-storage-v2/pom.xml b/proto-google-cloud-storage-v2/pom.xml index b480f4de1..6dcaf9449 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.35.0-alpha + 2.35.1-alpha-SNAPSHOT proto-google-cloud-storage-v2 PROTO library for proto-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.35.0 + 2.35.1-SNAPSHOT diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index a7d94eadf..d875f8e60 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-storage - 2.35.0 + 2.35.1-SNAPSHOT diff --git a/storage-shared-benchmarking/pom.xml b/storage-shared-benchmarking/pom.xml index 48d96cfa4..5bb630203 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.35.0 + 2.35.1-SNAPSHOT @@ -31,7 +31,7 @@ com.google.cloud google-cloud-storage - 2.35.0 + 2.35.1-SNAPSHOT tests diff --git a/versions.txt b/versions.txt index d9d4788b0..1ed68144a 100644 --- a/versions.txt +++ b/versions.txt @@ -1,10 +1,10 @@ # Format: # module:released-version:current-version -google-cloud-storage:2.35.0:2.35.0 -gapic-google-cloud-storage-v2:2.35.0-alpha:2.35.0-alpha -grpc-google-cloud-storage-v2:2.35.0-alpha:2.35.0-alpha -proto-google-cloud-storage-v2:2.35.0-alpha:2.35.0-alpha -google-cloud-storage-control:2.35.0-alpha:2.35.0-alpha -proto-google-cloud-storage-control-v2:2.35.0-alpha:2.35.0-alpha -grpc-google-cloud-storage-control-v2:2.35.0-alpha:2.35.0-alpha +google-cloud-storage:2.35.0:2.35.1-SNAPSHOT +gapic-google-cloud-storage-v2:2.35.0-alpha:2.35.1-alpha-SNAPSHOT +grpc-google-cloud-storage-v2:2.35.0-alpha:2.35.1-alpha-SNAPSHOT +proto-google-cloud-storage-v2:2.35.0-alpha:2.35.1-alpha-SNAPSHOT +google-cloud-storage-control:2.35.0-alpha:2.35.1-alpha-SNAPSHOT +proto-google-cloud-storage-control-v2:2.35.0-alpha:2.35.1-alpha-SNAPSHOT +grpc-google-cloud-storage-control-v2:2.35.0-alpha:2.35.1-alpha-SNAPSHOT From 54354d8dce0982536e42b526eb1a7c6ede1dd36e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 6 Mar 2024 20:24:39 +0100 Subject: [PATCH 02/14] chore(deps): update dependency com.google.cloud:google-cloud-storage to v2.35.0 (#2437) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): update dependency com.google.cloud:google-cloud-storage to v2.35.0 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- README.md | 8 ++++---- samples/install-without-bom/pom.xml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b8a64db06..e4a3cfd16 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ If you are using Maven without the BOM, add this to your dependencies: com.google.cloud google-cloud-storage - 2.34.0 + 2.35.0 ``` @@ -57,13 +57,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.34.0' +implementation 'com.google.cloud:google-cloud-storage:2.35.0' ``` If you are using SBT, add this to your dependencies: ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "2.34.0" +libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "2.35.0" ``` @@ -430,7 +430,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.34.0 +[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-storage/2.35.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/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index fc7eb017f..4603242fa 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-storage - 2.34.0 + 2.35.0 From 80745d415810353b3466a3eda12f6ca50a2c71b0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 11 Mar 2024 20:01:37 +0100 Subject: [PATCH 03/14] deps: update gcr.io/cloud-devrel-public-resources/storage-testbench docker tag to v0.42.0 (#2441) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update gcr.io/cloud-devrel-public-resources/storage-testbench docker tag to v0.42.0 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- README.md | 2 +- .../com/google/cloud/storage/it/runner/registry/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e4a3cfd16..829d3c7f5 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,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.33.0') +implementation platform('com.google.cloud:libraries-bom:26.34.0') implementation 'com.google.cloud:google-cloud-storage' ``` diff --git a/google-cloud-storage/src/test/resources/com/google/cloud/storage/it/runner/registry/Dockerfile b/google-cloud-storage/src/test/resources/com/google/cloud/storage/it/runner/registry/Dockerfile index 3d168312d..2c621adee 100644 --- a/google-cloud-storage/src/test/resources/com/google/cloud/storage/it/runner/registry/Dockerfile +++ b/google-cloud-storage/src/test/resources/com/google/cloud/storage/it/runner/registry/Dockerfile @@ -1 +1 @@ -FROM gcr.io/cloud-devrel-public-resources/storage-testbench:v0.41.0 +FROM gcr.io/cloud-devrel-public-resources/storage-testbench:v0.42.0 From e5055ef4fd09ece5f1fdc1d6c4d8a64ed19bd487 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 11 Mar 2024 20:02:06 +0100 Subject: [PATCH 04/14] chore(deps): update dependency com.google.cloud:libraries-bom to v26.34.0 (#2440) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): update dependency com.google.cloud:libraries-bom to v26.34.0 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- README.md | 2 +- samples/native-image-sample/pom.xml | 2 +- samples/snippets/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 829d3c7f5..90030c80a 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.33.0 + 26.34.0 pom import diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml index 9272f0fed..db9dad2f3 100644 --- a/samples/native-image-sample/pom.xml +++ b/samples/native-image-sample/pom.xml @@ -29,7 +29,7 @@ com.google.cloud libraries-bom - 26.33.0 + 26.34.0 pom import diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 765abc802..da562bc01 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -31,7 +31,7 @@ com.google.cloud libraries-bom - 26.33.0 + 26.34.0 pom import From 1352203859c3798423ef78823ed10577b93eebef Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 11 Mar 2024 20:03:48 +0100 Subject: [PATCH 05/14] deps: update dependency com.google.apis:google-api-services-storage to v1-rev20240307-2.0.0 (#2442) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deps: update dependency com.google.apis:google-api-services-storage to v1-rev20240307-2.0.0 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3d04204c7..6a1297cac 100644 --- a/pom.xml +++ b/pom.xml @@ -81,7 +81,7 @@ com.google.apis google-api-services-storage - v1-rev20240209-2.0.0 + v1-rev20240307-2.0.0 com.google.cloud From 254d2eaddfd514072d8b77f7d056f5bdd3f7c281 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 14:51:06 -0700 Subject: [PATCH 06/14] chore(feat): add hns to bucket metadata and include_folders_as_prefix to protos (#2433) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(deps): Update the Java code generator (gapic-generator-java) to 2.37.0 PiperOrigin-RevId: 611816371 Source-Link: https://github.com/googleapis/googleapis/commit/2a40f63ea714c7f4c6856a5db4d1f3cc7d4c4b18 Source-Link: https://github.com/googleapis/googleapis-gen/commit/d30ff0767777b381fb1617f67a90e3abd3bdc6dc Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiZDMwZmYwNzY3Nzc3YjM4MWZiMTYxN2Y2N2E5MGUzYWJkM2JkYzZkYyJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * feat: Support for creating HNS Bucket in C++ SDK PiperOrigin-RevId: 613689182 Source-Link: https://github.com/googleapis/googleapis/commit/8e2fbae4efbc7e47b61cdae4a49a660507c98c0d Source-Link: https://github.com/googleapis/googleapis-gen/commit/fb6e4b502be7066c9d0eec7213487463ade21b00 Copy-Tag: eyJwIjoiLmdpdGh1Yi8uT3dsQm90LnlhbWwiLCJoIjoiZmI2ZTRiNTAyYmU3MDY2YzlkMGVlYzcyMTM0ODc0NjNhZGUyMWIwMCJ9 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix clirr --------- Co-authored-by: Owl Bot Co-authored-by: Jesse Lovelace --- .../com/google/storage/v2/StorageClient.java | 3 + .../com.google.storage.v2/reflect-config.json | 18 + .../google/storage/v2/StorageClientTest.java | 7 + .../v2/stub/StorageControlStubSettings.java | 3 - .../clirr-ignored-differences.xml | 12 + .../java/com/google/storage/v2/Bucket.java | 891 +++++++++++++++++- .../google/storage/v2/BucketOrBuilder.java | 47 + .../google/storage/v2/ListObjectsRequest.java | 107 ++- .../v2/ListObjectsRequestOrBuilder.java | 14 + .../com/google/storage/v2/StorageProto.java | 833 ++++++++-------- .../proto/google/storage/v2/storage.proto | 17 + 11 files changed, 1525 insertions(+), 427 deletions(-) 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 83ed6ef70..cb1602940 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 @@ -3576,6 +3576,7 @@ public final ListObjectsPagedResponse listObjects(String parent) { * .setLexicographicStart("lexicographicStart-2093413008") * .setLexicographicEnd("lexicographicEnd1646968169") * .setSoftDeleted(true) + * .setIncludeFoldersAsPrefixes(true) * .setMatchGlob("matchGlob613636317") * .build(); * for (Object element : storageClient.listObjects(request).iterateAll()) { @@ -3617,6 +3618,7 @@ public final ListObjectsPagedResponse listObjects(ListObjectsRequest request) { * .setLexicographicStart("lexicographicStart-2093413008") * .setLexicographicEnd("lexicographicEnd1646968169") * .setSoftDeleted(true) + * .setIncludeFoldersAsPrefixes(true) * .setMatchGlob("matchGlob613636317") * .build(); * ApiFuture future = storageClient.listObjectsPagedCallable().futureCall(request); @@ -3658,6 +3660,7 @@ public final ListObjectsPagedResponse listObjects(ListObjectsRequest request) { * .setLexicographicStart("lexicographicStart-2093413008") * .setLexicographicEnd("lexicographicEnd1646968169") * .setSoftDeleted(true) + * .setIncludeFoldersAsPrefixes(true) * .setMatchGlob("matchGlob613636317") * .build(); * while (true) { 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 aedfd2a2d..534ec4357 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 @@ -1601,6 +1601,24 @@ "allDeclaredClasses": true, "allPublicClasses": true }, + { + "name": "com.google.storage.v2.Bucket$HierarchicalNamespace", + "queryAllDeclaredConstructors": true, + "queryAllPublicConstructors": true, + "queryAllDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "com.google.storage.v2.Bucket$HierarchicalNamespace$Builder", + "queryAllDeclaredConstructors": true, + "queryAllPublicConstructors": true, + "queryAllDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, { "name": "com.google.storage.v2.Bucket$IamConfig", "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 82a4c7b9a..0e97f7bb6 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 @@ -202,6 +202,7 @@ public void getBucketTest() throws Exception { .setSatisfiesPzs(true) .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build()) .setAutoclass(Bucket.Autoclass.newBuilder().build()) + .setHierarchicalNamespace(Bucket.HierarchicalNamespace.newBuilder().build()) .setSoftDeletePolicy(Bucket.SoftDeletePolicy.newBuilder().build()) .build(); mockStorage.addResponse(expectedResponse); @@ -268,6 +269,7 @@ public void getBucketTest2() throws Exception { .setSatisfiesPzs(true) .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build()) .setAutoclass(Bucket.Autoclass.newBuilder().build()) + .setHierarchicalNamespace(Bucket.HierarchicalNamespace.newBuilder().build()) .setSoftDeletePolicy(Bucket.SoftDeletePolicy.newBuilder().build()) .build(); mockStorage.addResponse(expectedResponse); @@ -334,6 +336,7 @@ public void createBucketTest() throws Exception { .setSatisfiesPzs(true) .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build()) .setAutoclass(Bucket.Autoclass.newBuilder().build()) + .setHierarchicalNamespace(Bucket.HierarchicalNamespace.newBuilder().build()) .setSoftDeletePolicy(Bucket.SoftDeletePolicy.newBuilder().build()) .build(); mockStorage.addResponse(expectedResponse); @@ -406,6 +409,7 @@ public void createBucketTest2() throws Exception { .setSatisfiesPzs(true) .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build()) .setAutoclass(Bucket.Autoclass.newBuilder().build()) + .setHierarchicalNamespace(Bucket.HierarchicalNamespace.newBuilder().build()) .setSoftDeletePolicy(Bucket.SoftDeletePolicy.newBuilder().build()) .build(); mockStorage.addResponse(expectedResponse); @@ -566,6 +570,7 @@ public void lockBucketRetentionPolicyTest() throws Exception { .setSatisfiesPzs(true) .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build()) .setAutoclass(Bucket.Autoclass.newBuilder().build()) + .setHierarchicalNamespace(Bucket.HierarchicalNamespace.newBuilder().build()) .setSoftDeletePolicy(Bucket.SoftDeletePolicy.newBuilder().build()) .build(); mockStorage.addResponse(expectedResponse); @@ -633,6 +638,7 @@ public void lockBucketRetentionPolicyTest2() throws Exception { .setSatisfiesPzs(true) .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build()) .setAutoclass(Bucket.Autoclass.newBuilder().build()) + .setHierarchicalNamespace(Bucket.HierarchicalNamespace.newBuilder().build()) .setSoftDeletePolicy(Bucket.SoftDeletePolicy.newBuilder().build()) .build(); mockStorage.addResponse(expectedResponse); @@ -954,6 +960,7 @@ public void updateBucketTest() throws Exception { .setSatisfiesPzs(true) .setCustomPlacementConfig(Bucket.CustomPlacementConfig.newBuilder().build()) .setAutoclass(Bucket.Autoclass.newBuilder().build()) + .setHierarchicalNamespace(Bucket.HierarchicalNamespace.newBuilder().build()) .setSoftDeletePolicy(Bucket.SoftDeletePolicy.newBuilder().build()) .build(); mockStorage.addResponse(expectedResponse); diff --git a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStubSettings.java b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStubSettings.java index c65cddfce..c1bf741c1 100644 --- a/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStubSettings.java +++ b/google-cloud-storage-control/src/main/java/com/google/storage/control/v2/stub/StorageControlStubSettings.java @@ -20,7 +20,6 @@ import com.google.api.core.ApiFunction; import com.google.api.core.ApiFuture; -import com.google.api.core.BetaApi; import com.google.api.gax.core.GaxProperties; import com.google.api.gax.core.GoogleCredentialsProvider; import com.google.api.gax.core.InstantiatingExecutorProvider; @@ -533,8 +532,6 @@ public UnaryCallSettings.Builder renameFolderSet } /** Returns the builder for the settings used for calls to renameFolder. */ - @BetaApi( - "The surface for use by generated code is not stable yet and may change in the future.") public OperationCallSettings.Builder renameFolderOperationSettings() { return renameFolderOperationSettings; diff --git a/proto-google-cloud-storage-v2/clirr-ignored-differences.xml b/proto-google-cloud-storage-v2/clirr-ignored-differences.xml index 32b659c45..61451374b 100644 --- a/proto-google-cloud-storage-v2/clirr-ignored-differences.xml +++ b/proto-google-cloud-storage-v2/clirr-ignored-differences.xml @@ -66,4 +66,16 @@ com/google/storage/v2/* * *HardDeleteTime*(*) + + + 7012 + com/google/storage/v2/* + * *HierarchicalNamespace*(*) + + + + 7012 + com/google/storage/v2/* + * *IncludeFoldersAsPrefixes*(*) + diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Bucket.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Bucket.java index faca15fda..347b9632a 100644 --- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Bucket.java +++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/Bucket.java @@ -18085,6 +18085,545 @@ public com.google.storage.v2.Bucket.Autoclass getDefaultInstanceForType() { } } + public interface HierarchicalNamespaceOrBuilder + extends + // @@protoc_insertion_point(interface_extends:google.storage.v2.Bucket.HierarchicalNamespace) + com.google.protobuf.MessageOrBuilder { + + /** + * + * + *
+     * Optional. Enables the hierarchical namespace feature.
+     * 
+ * + * bool enabled = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The enabled. + */ + boolean getEnabled(); + } + /** + * + * + *
+   * Configuration for a bucket's hierarchical namespace feature.
+   * 
+ * + * Protobuf type {@code google.storage.v2.Bucket.HierarchicalNamespace} + */ + public static final class HierarchicalNamespace extends com.google.protobuf.GeneratedMessageV3 + implements + // @@protoc_insertion_point(message_implements:google.storage.v2.Bucket.HierarchicalNamespace) + HierarchicalNamespaceOrBuilder { + private static final long serialVersionUID = 0L; + // Use HierarchicalNamespace.newBuilder() to construct. + private HierarchicalNamespace(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + + private HierarchicalNamespace() {} + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance(UnusedPrivateParameter unused) { + return new HierarchicalNamespace(); + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_Bucket_HierarchicalNamespace_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_Bucket_HierarchicalNamespace_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.google.storage.v2.Bucket.HierarchicalNamespace.class, + com.google.storage.v2.Bucket.HierarchicalNamespace.Builder.class); + } + + public static final int ENABLED_FIELD_NUMBER = 1; + private boolean enabled_ = false; + /** + * + * + *
+     * Optional. Enables the hierarchical namespace feature.
+     * 
+ * + * bool enabled = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The enabled. + */ + @java.lang.Override + public boolean getEnabled() { + return enabled_; + } + + 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 (enabled_ != false) { + output.writeBool(1, enabled_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (enabled_ != false) { + size += com.google.protobuf.CodedOutputStream.computeBoolSize(1, enabled_); + } + 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.Bucket.HierarchicalNamespace)) { + return super.equals(obj); + } + com.google.storage.v2.Bucket.HierarchicalNamespace other = + (com.google.storage.v2.Bucket.HierarchicalNamespace) obj; + + if (getEnabled() != other.getEnabled()) 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) + ENABLED_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(getEnabled()); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.google.storage.v2.Bucket.HierarchicalNamespace parseFrom( + java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.storage.v2.Bucket.HierarchicalNamespace 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.Bucket.HierarchicalNamespace parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.storage.v2.Bucket.HierarchicalNamespace 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.Bucket.HierarchicalNamespace parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.storage.v2.Bucket.HierarchicalNamespace parseFrom( + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.storage.v2.Bucket.HierarchicalNamespace parseFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); + } + + public static com.google.storage.v2.Bucket.HierarchicalNamespace 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.Bucket.HierarchicalNamespace parseDelimitedFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input); + } + + public static com.google.storage.v2.Bucket.HierarchicalNamespace 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.Bucket.HierarchicalNamespace parseFrom( + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input); + } + + public static com.google.storage.v2.Bucket.HierarchicalNamespace 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.Bucket.HierarchicalNamespace 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; + } + /** + * + * + *
+     * Configuration for a bucket's hierarchical namespace feature.
+     * 
+ * + * Protobuf type {@code google.storage.v2.Bucket.HierarchicalNamespace} + */ + public static final class Builder + extends com.google.protobuf.GeneratedMessageV3.Builder + implements + // @@protoc_insertion_point(builder_implements:google.storage.v2.Bucket.HierarchicalNamespace) + com.google.storage.v2.Bucket.HierarchicalNamespaceOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_Bucket_HierarchicalNamespace_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_Bucket_HierarchicalNamespace_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.google.storage.v2.Bucket.HierarchicalNamespace.class, + com.google.storage.v2.Bucket.HierarchicalNamespace.Builder.class); + } + + // Construct using com.google.storage.v2.Bucket.HierarchicalNamespace.newBuilder() + private Builder() {} + + private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + } + + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + enabled_ = false; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.google.storage.v2.StorageProto + .internal_static_google_storage_v2_Bucket_HierarchicalNamespace_descriptor; + } + + @java.lang.Override + public com.google.storage.v2.Bucket.HierarchicalNamespace getDefaultInstanceForType() { + return com.google.storage.v2.Bucket.HierarchicalNamespace.getDefaultInstance(); + } + + @java.lang.Override + public com.google.storage.v2.Bucket.HierarchicalNamespace build() { + com.google.storage.v2.Bucket.HierarchicalNamespace result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.google.storage.v2.Bucket.HierarchicalNamespace buildPartial() { + com.google.storage.v2.Bucket.HierarchicalNamespace result = + new com.google.storage.v2.Bucket.HierarchicalNamespace(this); + if (bitField0_ != 0) { + buildPartial0(result); + } + onBuilt(); + return result; + } + + private void buildPartial0(com.google.storage.v2.Bucket.HierarchicalNamespace result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.enabled_ = enabled_; + } + } + + @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.Bucket.HierarchicalNamespace) { + return mergeFrom((com.google.storage.v2.Bucket.HierarchicalNamespace) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.google.storage.v2.Bucket.HierarchicalNamespace other) { + if (other == com.google.storage.v2.Bucket.HierarchicalNamespace.getDefaultInstance()) + return this; + if (other.getEnabled() != false) { + setEnabled(other.getEnabled()); + } + 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 8: + { + enabled_ = input.readBool(); + bitField0_ |= 0x00000001; + break; + } // case 8 + 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 boolean enabled_; + /** + * + * + *
+       * Optional. Enables the hierarchical namespace feature.
+       * 
+ * + * bool enabled = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The enabled. + */ + @java.lang.Override + public boolean getEnabled() { + return enabled_; + } + /** + * + * + *
+       * Optional. Enables the hierarchical namespace feature.
+       * 
+ * + * bool enabled = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + * @param value The enabled to set. + * @return This builder for chaining. + */ + public Builder setEnabled(boolean value) { + + enabled_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * + * + *
+       * Optional. Enables the hierarchical namespace feature.
+       * 
+ * + * bool enabled = 1 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return This builder for chaining. + */ + public Builder clearEnabled() { + bitField0_ = (bitField0_ & ~0x00000001); + enabled_ = false; + onChanged(); + return this; + } + + @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.Bucket.HierarchicalNamespace) + } + + // @@protoc_insertion_point(class_scope:google.storage.v2.Bucket.HierarchicalNamespace) + private static final com.google.storage.v2.Bucket.HierarchicalNamespace DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new com.google.storage.v2.Bucket.HierarchicalNamespace(); + } + + public static com.google.storage.v2.Bucket.HierarchicalNamespace getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public HierarchicalNamespace 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.Bucket.HierarchicalNamespace getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + } + private int bitField0_; public static final int NAME_FIELD_NUMBER = 1; @@ -19635,6 +20174,69 @@ public com.google.storage.v2.Bucket.AutoclassOrBuilder getAutoclassOrBuilder() { : autoclass_; } + public static final int HIERARCHICAL_NAMESPACE_FIELD_NUMBER = 32; + private com.google.storage.v2.Bucket.HierarchicalNamespace hierarchicalNamespace_; + /** + * + * + *
+   * Optional. The bucket's hierarchical namespace configuration. If there is no
+   * configuration, the hierarchical namespace feature will be disabled and have
+   * no effect on the bucket.
+   * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return Whether the hierarchicalNamespace field is set. + */ + @java.lang.Override + public boolean hasHierarchicalNamespace() { + return ((bitField0_ & 0x00002000) != 0); + } + /** + * + * + *
+   * Optional. The bucket's hierarchical namespace configuration. If there is no
+   * configuration, the hierarchical namespace feature will be disabled and have
+   * no effect on the bucket.
+   * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return The hierarchicalNamespace. + */ + @java.lang.Override + public com.google.storage.v2.Bucket.HierarchicalNamespace getHierarchicalNamespace() { + return hierarchicalNamespace_ == null + ? com.google.storage.v2.Bucket.HierarchicalNamespace.getDefaultInstance() + : hierarchicalNamespace_; + } + /** + * + * + *
+   * Optional. The bucket's hierarchical namespace configuration. If there is no
+   * configuration, the hierarchical namespace feature will be disabled and have
+   * no effect on the bucket.
+   * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + @java.lang.Override + public com.google.storage.v2.Bucket.HierarchicalNamespaceOrBuilder + getHierarchicalNamespaceOrBuilder() { + return hierarchicalNamespace_ == null + ? com.google.storage.v2.Bucket.HierarchicalNamespace.getDefaultInstance() + : hierarchicalNamespace_; + } + public static final int SOFT_DELETE_POLICY_FIELD_NUMBER = 31; private com.google.storage.v2.Bucket.SoftDeletePolicy softDeletePolicy_; /** @@ -19653,7 +20255,7 @@ public com.google.storage.v2.Bucket.AutoclassOrBuilder getAutoclassOrBuilder() { */ @java.lang.Override public boolean hasSoftDeletePolicy() { - return ((bitField0_ & 0x00002000) != 0); + return ((bitField0_ & 0x00004000) != 0); } /** * @@ -19791,9 +20393,12 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 29, etag_); } - if (((bitField0_ & 0x00002000) != 0)) { + if (((bitField0_ & 0x00004000) != 0)) { output.writeMessage(31, getSoftDeletePolicy()); } + if (((bitField0_ & 0x00002000) != 0)) { + output.writeMessage(32, getHierarchicalNamespace()); + } getUnknownFields().writeTo(output); } @@ -19895,9 +20500,13 @@ public int getSerializedSize() { if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(etag_)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(29, etag_); } - if (((bitField0_ & 0x00002000) != 0)) { + if (((bitField0_ & 0x00004000) != 0)) { size += com.google.protobuf.CodedOutputStream.computeMessageSize(31, getSoftDeletePolicy()); } + if (((bitField0_ & 0x00002000) != 0)) { + size += + com.google.protobuf.CodedOutputStream.computeMessageSize(32, getHierarchicalNamespace()); + } size += getUnknownFields().getSerializedSize(); memoizedSize = size; return size; @@ -19980,6 +20589,10 @@ public boolean equals(final java.lang.Object obj) { if (hasAutoclass()) { if (!getAutoclass().equals(other.getAutoclass())) return false; } + if (hasHierarchicalNamespace() != other.hasHierarchicalNamespace()) return false; + if (hasHierarchicalNamespace()) { + if (!getHierarchicalNamespace().equals(other.getHierarchicalNamespace())) return false; + } if (hasSoftDeletePolicy() != other.hasSoftDeletePolicy()) return false; if (hasSoftDeletePolicy()) { if (!getSoftDeletePolicy().equals(other.getSoftDeletePolicy())) return false; @@ -20085,6 +20698,10 @@ public int hashCode() { hash = (37 * hash) + AUTOCLASS_FIELD_NUMBER; hash = (53 * hash) + getAutoclass().hashCode(); } + if (hasHierarchicalNamespace()) { + hash = (37 * hash) + HIERARCHICAL_NAMESPACE_FIELD_NUMBER; + hash = (53 * hash) + getHierarchicalNamespace().hashCode(); + } if (hasSoftDeletePolicy()) { hash = (37 * hash) + SOFT_DELETE_POLICY_FIELD_NUMBER; hash = (53 * hash) + getSoftDeletePolicy().hashCode(); @@ -20264,6 +20881,7 @@ private void maybeForceBuilderInitialization() { getIamConfigFieldBuilder(); getCustomPlacementConfigFieldBuilder(); getAutoclassFieldBuilder(); + getHierarchicalNamespaceFieldBuilder(); getSoftDeletePolicyFieldBuilder(); } } @@ -20370,6 +20988,11 @@ public Builder clear() { autoclassBuilder_.dispose(); autoclassBuilder_ = null; } + hierarchicalNamespace_ = null; + if (hierarchicalNamespaceBuilder_ != null) { + hierarchicalNamespaceBuilder_.dispose(); + hierarchicalNamespaceBuilder_ = null; + } softDeletePolicy_ = null; if (softDeletePolicyBuilder_ != null) { softDeletePolicyBuilder_.dispose(); @@ -20535,9 +21158,16 @@ private void buildPartial0(com.google.storage.v2.Bucket result) { to_bitField0_ |= 0x00001000; } if (((from_bitField0_ & 0x10000000) != 0)) { + result.hierarchicalNamespace_ = + hierarchicalNamespaceBuilder_ == null + ? hierarchicalNamespace_ + : hierarchicalNamespaceBuilder_.build(); + to_bitField0_ |= 0x00002000; + } + if (((from_bitField0_ & 0x20000000) != 0)) { result.softDeletePolicy_ = softDeletePolicyBuilder_ == null ? softDeletePolicy_ : softDeletePolicyBuilder_.build(); - to_bitField0_ |= 0x00002000; + to_bitField0_ |= 0x00004000; } result.bitField0_ |= to_bitField0_; } @@ -20758,6 +21388,9 @@ public Builder mergeFrom(com.google.storage.v2.Bucket other) { if (other.hasAutoclass()) { mergeAutoclass(other.getAutoclass()); } + if (other.hasHierarchicalNamespace()) { + mergeHierarchicalNamespace(other.getHierarchicalNamespace()); + } if (other.hasSoftDeletePolicy()) { mergeSoftDeletePolicy(other.getSoftDeletePolicy()); } @@ -20987,9 +21620,16 @@ public Builder mergeFrom( { input.readMessage( getSoftDeletePolicyFieldBuilder().getBuilder(), extensionRegistry); - bitField0_ |= 0x10000000; + bitField0_ |= 0x20000000; break; } // case 250 + case 258: + { + input.readMessage( + getHierarchicalNamespaceFieldBuilder().getBuilder(), extensionRegistry); + bitField0_ |= 0x10000000; + break; + } // case 258 default: { if (!super.parseUnknownField(input, extensionRegistry, tag)) { @@ -26086,6 +26726,233 @@ public com.google.storage.v2.Bucket.AutoclassOrBuilder getAutoclassOrBuilder() { return autoclassBuilder_; } + private com.google.storage.v2.Bucket.HierarchicalNamespace hierarchicalNamespace_; + private com.google.protobuf.SingleFieldBuilderV3< + com.google.storage.v2.Bucket.HierarchicalNamespace, + com.google.storage.v2.Bucket.HierarchicalNamespace.Builder, + com.google.storage.v2.Bucket.HierarchicalNamespaceOrBuilder> + hierarchicalNamespaceBuilder_; + /** + * + * + *
+     * Optional. The bucket's hierarchical namespace configuration. If there is no
+     * configuration, the hierarchical namespace feature will be disabled and have
+     * no effect on the bucket.
+     * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return Whether the hierarchicalNamespace field is set. + */ + public boolean hasHierarchicalNamespace() { + return ((bitField0_ & 0x10000000) != 0); + } + /** + * + * + *
+     * Optional. The bucket's hierarchical namespace configuration. If there is no
+     * configuration, the hierarchical namespace feature will be disabled and have
+     * no effect on the bucket.
+     * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return The hierarchicalNamespace. + */ + public com.google.storage.v2.Bucket.HierarchicalNamespace getHierarchicalNamespace() { + if (hierarchicalNamespaceBuilder_ == null) { + return hierarchicalNamespace_ == null + ? com.google.storage.v2.Bucket.HierarchicalNamespace.getDefaultInstance() + : hierarchicalNamespace_; + } else { + return hierarchicalNamespaceBuilder_.getMessage(); + } + } + /** + * + * + *
+     * Optional. The bucket's hierarchical namespace configuration. If there is no
+     * configuration, the hierarchical namespace feature will be disabled and have
+     * no effect on the bucket.
+     * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public Builder setHierarchicalNamespace( + com.google.storage.v2.Bucket.HierarchicalNamespace value) { + if (hierarchicalNamespaceBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + hierarchicalNamespace_ = value; + } else { + hierarchicalNamespaceBuilder_.setMessage(value); + } + bitField0_ |= 0x10000000; + onChanged(); + return this; + } + /** + * + * + *
+     * Optional. The bucket's hierarchical namespace configuration. If there is no
+     * configuration, the hierarchical namespace feature will be disabled and have
+     * no effect on the bucket.
+     * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public Builder setHierarchicalNamespace( + com.google.storage.v2.Bucket.HierarchicalNamespace.Builder builderForValue) { + if (hierarchicalNamespaceBuilder_ == null) { + hierarchicalNamespace_ = builderForValue.build(); + } else { + hierarchicalNamespaceBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x10000000; + onChanged(); + return this; + } + /** + * + * + *
+     * Optional. The bucket's hierarchical namespace configuration. If there is no
+     * configuration, the hierarchical namespace feature will be disabled and have
+     * no effect on the bucket.
+     * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public Builder mergeHierarchicalNamespace( + com.google.storage.v2.Bucket.HierarchicalNamespace value) { + if (hierarchicalNamespaceBuilder_ == null) { + if (((bitField0_ & 0x10000000) != 0) + && hierarchicalNamespace_ != null + && hierarchicalNamespace_ + != com.google.storage.v2.Bucket.HierarchicalNamespace.getDefaultInstance()) { + getHierarchicalNamespaceBuilder().mergeFrom(value); + } else { + hierarchicalNamespace_ = value; + } + } else { + hierarchicalNamespaceBuilder_.mergeFrom(value); + } + if (hierarchicalNamespace_ != null) { + bitField0_ |= 0x10000000; + onChanged(); + } + return this; + } + /** + * + * + *
+     * Optional. The bucket's hierarchical namespace configuration. If there is no
+     * configuration, the hierarchical namespace feature will be disabled and have
+     * no effect on the bucket.
+     * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public Builder clearHierarchicalNamespace() { + bitField0_ = (bitField0_ & ~0x10000000); + hierarchicalNamespace_ = null; + if (hierarchicalNamespaceBuilder_ != null) { + hierarchicalNamespaceBuilder_.dispose(); + hierarchicalNamespaceBuilder_ = null; + } + onChanged(); + return this; + } + /** + * + * + *
+     * Optional. The bucket's hierarchical namespace configuration. If there is no
+     * configuration, the hierarchical namespace feature will be disabled and have
+     * no effect on the bucket.
+     * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public com.google.storage.v2.Bucket.HierarchicalNamespace.Builder + getHierarchicalNamespaceBuilder() { + bitField0_ |= 0x10000000; + onChanged(); + return getHierarchicalNamespaceFieldBuilder().getBuilder(); + } + /** + * + * + *
+     * Optional. The bucket's hierarchical namespace configuration. If there is no
+     * configuration, the hierarchical namespace feature will be disabled and have
+     * no effect on the bucket.
+     * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + public com.google.storage.v2.Bucket.HierarchicalNamespaceOrBuilder + getHierarchicalNamespaceOrBuilder() { + if (hierarchicalNamespaceBuilder_ != null) { + return hierarchicalNamespaceBuilder_.getMessageOrBuilder(); + } else { + return hierarchicalNamespace_ == null + ? com.google.storage.v2.Bucket.HierarchicalNamespace.getDefaultInstance() + : hierarchicalNamespace_; + } + } + /** + * + * + *
+     * Optional. The bucket's hierarchical namespace configuration. If there is no
+     * configuration, the hierarchical namespace feature will be disabled and have
+     * no effect on the bucket.
+     * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + private com.google.protobuf.SingleFieldBuilderV3< + com.google.storage.v2.Bucket.HierarchicalNamespace, + com.google.storage.v2.Bucket.HierarchicalNamespace.Builder, + com.google.storage.v2.Bucket.HierarchicalNamespaceOrBuilder> + getHierarchicalNamespaceFieldBuilder() { + if (hierarchicalNamespaceBuilder_ == null) { + hierarchicalNamespaceBuilder_ = + new com.google.protobuf.SingleFieldBuilderV3< + com.google.storage.v2.Bucket.HierarchicalNamespace, + com.google.storage.v2.Bucket.HierarchicalNamespace.Builder, + com.google.storage.v2.Bucket.HierarchicalNamespaceOrBuilder>( + getHierarchicalNamespace(), getParentForChildren(), isClean()); + hierarchicalNamespace_ = null; + } + return hierarchicalNamespaceBuilder_; + } + private com.google.storage.v2.Bucket.SoftDeletePolicy softDeletePolicy_; private com.google.protobuf.SingleFieldBuilderV3< com.google.storage.v2.Bucket.SoftDeletePolicy, @@ -26107,7 +26974,7 @@ public com.google.storage.v2.Bucket.AutoclassOrBuilder getAutoclassOrBuilder() { * @return Whether the softDeletePolicy field is set. */ public boolean hasSoftDeletePolicy() { - return ((bitField0_ & 0x10000000) != 0); + return ((bitField0_ & 0x20000000) != 0); } /** * @@ -26153,7 +27020,7 @@ public Builder setSoftDeletePolicy(com.google.storage.v2.Bucket.SoftDeletePolicy } else { softDeletePolicyBuilder_.setMessage(value); } - bitField0_ |= 0x10000000; + bitField0_ |= 0x20000000; onChanged(); return this; } @@ -26176,7 +27043,7 @@ public Builder setSoftDeletePolicy( } else { softDeletePolicyBuilder_.setMessage(builderForValue.build()); } - bitField0_ |= 0x10000000; + bitField0_ |= 0x20000000; onChanged(); return this; } @@ -26194,7 +27061,7 @@ public Builder setSoftDeletePolicy( */ public Builder mergeSoftDeletePolicy(com.google.storage.v2.Bucket.SoftDeletePolicy value) { if (softDeletePolicyBuilder_ == null) { - if (((bitField0_ & 0x10000000) != 0) + if (((bitField0_ & 0x20000000) != 0) && softDeletePolicy_ != null && softDeletePolicy_ != com.google.storage.v2.Bucket.SoftDeletePolicy.getDefaultInstance()) { @@ -26206,7 +27073,7 @@ public Builder mergeSoftDeletePolicy(com.google.storage.v2.Bucket.SoftDeletePoli softDeletePolicyBuilder_.mergeFrom(value); } if (softDeletePolicy_ != null) { - bitField0_ |= 0x10000000; + bitField0_ |= 0x20000000; onChanged(); } return this; @@ -26224,7 +27091,7 @@ public Builder mergeSoftDeletePolicy(com.google.storage.v2.Bucket.SoftDeletePoli * */ public Builder clearSoftDeletePolicy() { - bitField0_ = (bitField0_ & ~0x10000000); + bitField0_ = (bitField0_ & ~0x20000000); softDeletePolicy_ = null; if (softDeletePolicyBuilder_ != null) { softDeletePolicyBuilder_.dispose(); @@ -26246,7 +27113,7 @@ public Builder clearSoftDeletePolicy() { * */ public com.google.storage.v2.Bucket.SoftDeletePolicy.Builder getSoftDeletePolicyBuilder() { - bitField0_ |= 0x10000000; + bitField0_ |= 0x20000000; onChanged(); return getSoftDeletePolicyFieldBuilder().getBuilder(); } diff --git a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketOrBuilder.java b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketOrBuilder.java index 41ca1c716..8c6c315be 100644 --- a/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketOrBuilder.java +++ b/proto-google-cloud-storage-v2/src/main/java/com/google/storage/v2/BucketOrBuilder.java @@ -1075,6 +1075,53 @@ java.lang.String getLabelsOrDefault( */ com.google.storage.v2.Bucket.AutoclassOrBuilder getAutoclassOrBuilder(); + /** + * + * + *
+   * Optional. The bucket's hierarchical namespace configuration. If there is no
+   * configuration, the hierarchical namespace feature will be disabled and have
+   * no effect on the bucket.
+   * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return Whether the hierarchicalNamespace field is set. + */ + boolean hasHierarchicalNamespace(); + /** + * + * + *
+   * Optional. The bucket's hierarchical namespace configuration. If there is no
+   * configuration, the hierarchical namespace feature will be disabled and have
+   * no effect on the bucket.
+   * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + * + * @return The hierarchicalNamespace. + */ + com.google.storage.v2.Bucket.HierarchicalNamespace getHierarchicalNamespace(); + /** + * + * + *
+   * Optional. The bucket's hierarchical namespace configuration. If there is no
+   * configuration, the hierarchical namespace feature will be disabled and have
+   * no effect on the bucket.
+   * 
+ * + * + * .google.storage.v2.Bucket.HierarchicalNamespace hierarchical_namespace = 32 [(.google.api.field_behavior) = OPTIONAL]; + * + */ + com.google.storage.v2.Bucket.HierarchicalNamespaceOrBuilder getHierarchicalNamespaceOrBuilder(); + /** * * 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 043db519f..22ec3b58e 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 @@ -540,6 +540,25 @@ public boolean getSoftDeleted() { return softDeleted_; } + public static final int INCLUDE_FOLDERS_AS_PREFIXES_FIELD_NUMBER = 13; + private boolean includeFoldersAsPrefixes_ = false; + /** + * + * + *
+   * Optional. If true, will also include folders and managed folders (besides
+   * objects) in the returned `prefixes`. Requires `delimiter` to be set to '/'.
+   * 
+ * + * bool include_folders_as_prefixes = 13 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The includeFoldersAsPrefixes. + */ + @java.lang.Override + public boolean getIncludeFoldersAsPrefixes() { + return includeFoldersAsPrefixes_; + } + public static final int MATCH_GLOB_FIELD_NUMBER = 14; @SuppressWarnings("serial") @@ -644,6 +663,9 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io if (softDeleted_ != false) { output.writeBool(12, softDeleted_); } + if (includeFoldersAsPrefixes_ != false) { + output.writeBool(13, includeFoldersAsPrefixes_); + } if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(matchGlob_)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 14, matchGlob_); } @@ -689,6 +711,9 @@ public int getSerializedSize() { if (softDeleted_ != false) { size += com.google.protobuf.CodedOutputStream.computeBoolSize(12, softDeleted_); } + if (includeFoldersAsPrefixes_ != false) { + size += com.google.protobuf.CodedOutputStream.computeBoolSize(13, includeFoldersAsPrefixes_); + } if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(matchGlob_)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(14, matchGlob_); } @@ -721,6 +746,7 @@ public boolean equals(final java.lang.Object obj) { if (!getLexicographicStart().equals(other.getLexicographicStart())) return false; if (!getLexicographicEnd().equals(other.getLexicographicEnd())) return false; if (getSoftDeleted() != other.getSoftDeleted()) return false; + if (getIncludeFoldersAsPrefixes() != other.getIncludeFoldersAsPrefixes()) return false; if (!getMatchGlob().equals(other.getMatchGlob())) return false; if (!getUnknownFields().equals(other.getUnknownFields())) return false; return true; @@ -757,6 +783,8 @@ public int hashCode() { hash = (53 * hash) + getLexicographicEnd().hashCode(); hash = (37 * hash) + SOFT_DELETED_FIELD_NUMBER; hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(getSoftDeleted()); + hash = (37 * hash) + INCLUDE_FOLDERS_AS_PREFIXES_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(getIncludeFoldersAsPrefixes()); hash = (37 * hash) + MATCH_GLOB_FIELD_NUMBER; hash = (53 * hash) + getMatchGlob().hashCode(); hash = (29 * hash) + getUnknownFields().hashCode(); @@ -922,6 +950,7 @@ public Builder clear() { lexicographicStart_ = ""; lexicographicEnd_ = ""; softDeleted_ = false; + includeFoldersAsPrefixes_ = false; matchGlob_ = ""; return this; } @@ -995,6 +1024,9 @@ private void buildPartial0(com.google.storage.v2.ListObjectsRequest result) { result.softDeleted_ = softDeleted_; } if (((from_bitField0_ & 0x00000800) != 0)) { + result.includeFoldersAsPrefixes_ = includeFoldersAsPrefixes_; + } + if (((from_bitField0_ & 0x00001000) != 0)) { result.matchGlob_ = matchGlob_; } result.bitField0_ |= to_bitField0_; @@ -1090,9 +1122,12 @@ public Builder mergeFrom(com.google.storage.v2.ListObjectsRequest other) { if (other.getSoftDeleted() != false) { setSoftDeleted(other.getSoftDeleted()); } + if (other.getIncludeFoldersAsPrefixes() != false) { + setIncludeFoldersAsPrefixes(other.getIncludeFoldersAsPrefixes()); + } if (!other.getMatchGlob().isEmpty()) { matchGlob_ = other.matchGlob_; - bitField0_ |= 0x00000800; + bitField0_ |= 0x00001000; onChanged(); } this.mergeUnknownFields(other.getUnknownFields()); @@ -1187,10 +1222,16 @@ public Builder mergeFrom( bitField0_ |= 0x00000400; break; } // case 96 + case 104: + { + includeFoldersAsPrefixes_ = input.readBool(); + bitField0_ |= 0x00000800; + break; + } // case 104 case 114: { matchGlob_ = input.readStringRequireUtf8(); - bitField0_ |= 0x00000800; + bitField0_ |= 0x00001000; break; } // case 114 default: @@ -2365,6 +2406,62 @@ public Builder clearSoftDeleted() { return this; } + private boolean includeFoldersAsPrefixes_; + /** + * + * + *
+     * Optional. If true, will also include folders and managed folders (besides
+     * objects) in the returned `prefixes`. Requires `delimiter` to be set to '/'.
+     * 
+ * + * bool include_folders_as_prefixes = 13 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The includeFoldersAsPrefixes. + */ + @java.lang.Override + public boolean getIncludeFoldersAsPrefixes() { + return includeFoldersAsPrefixes_; + } + /** + * + * + *
+     * Optional. If true, will also include folders and managed folders (besides
+     * objects) in the returned `prefixes`. Requires `delimiter` to be set to '/'.
+     * 
+ * + * bool include_folders_as_prefixes = 13 [(.google.api.field_behavior) = OPTIONAL]; + * + * @param value The includeFoldersAsPrefixes to set. + * @return This builder for chaining. + */ + public Builder setIncludeFoldersAsPrefixes(boolean value) { + + includeFoldersAsPrefixes_ = value; + bitField0_ |= 0x00000800; + onChanged(); + return this; + } + /** + * + * + *
+     * Optional. If true, will also include folders and managed folders (besides
+     * objects) in the returned `prefixes`. Requires `delimiter` to be set to '/'.
+     * 
+ * + * bool include_folders_as_prefixes = 13 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return This builder for chaining. + */ + public Builder clearIncludeFoldersAsPrefixes() { + bitField0_ = (bitField0_ & ~0x00000800); + includeFoldersAsPrefixes_ = false; + onChanged(); + return this; + } + private java.lang.Object matchGlob_ = ""; /** * @@ -2436,7 +2533,7 @@ public Builder setMatchGlob(java.lang.String value) { throw new NullPointerException(); } matchGlob_ = value; - bitField0_ |= 0x00000800; + bitField0_ |= 0x00001000; onChanged(); return this; } @@ -2456,7 +2553,7 @@ public Builder setMatchGlob(java.lang.String value) { */ public Builder clearMatchGlob() { matchGlob_ = getDefaultInstance().getMatchGlob(); - bitField0_ = (bitField0_ & ~0x00000800); + bitField0_ = (bitField0_ & ~0x00001000); onChanged(); return this; } @@ -2481,7 +2578,7 @@ public Builder setMatchGlobBytes(com.google.protobuf.ByteString value) { } checkByteStringIsUtf8(value); matchGlob_ = value; - bitField0_ |= 0x00000800; + bitField0_ |= 0x00001000; onChanged(); return this; } 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 34a381657..215d9afc5 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 @@ -307,6 +307,20 @@ public interface ListObjectsRequestOrBuilder */ boolean getSoftDeleted(); + /** + * + * + *
+   * Optional. If true, will also include folders and managed folders (besides
+   * objects) in the returned `prefixes`. Requires `delimiter` to be set to '/'.
+   * 
+ * + * bool include_folders_as_prefixes = 13 [(.google.api.field_behavior) = OPTIONAL]; + * + * @return The includeFoldersAsPrefixes. + */ + boolean getIncludeFoldersAsPrefixes(); + /** * * 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 7c9d8f224..fab5bd682 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 @@ -276,6 +276,10 @@ public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry r internal_static_google_storage_v2_Bucket_Autoclass_descriptor; static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_google_storage_v2_Bucket_Autoclass_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_google_storage_v2_Bucket_HierarchicalNamespace_descriptor; + static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_google_storage_v2_Bucket_HierarchicalNamespace_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor internal_static_google_storage_v2_Bucket_LabelsEntry_descriptor; static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable @@ -528,7 +532,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "\006\n\004data\"r\n\027BidiWriteObjectResponse\022\030\n\016pe" + "rsisted_size\030\001 \001(\003H\000\022-\n\010resource\030\002 \001(\0132\031" + ".google.storage.v2.ObjectH\000B\016\n\014write_sta" - + "tus\"\203\003\n\022ListObjectsRequest\0225\n\006parent\030\001 \001" + + "tus\"\255\003\n\022ListObjectsRequest\0225\n\006parent\030\001 \001" + "(\tB%\340A\002\372A\037\n\035storage.googleapis.com/Bucke" + "t\022\021\n\tpage_size\030\002 \001(\005\022\022\n\npage_token\030\003 \001(\t" + "\022\021\n\tdelimiter\030\004 \001(\t\022\"\n\032include_trailing_" @@ -536,411 +540,416 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "ons\030\007 \001(\010\0222\n\tread_mask\030\010 \001(\0132\032.google.pr" + "otobuf.FieldMaskH\000\210\001\001\022 \n\023lexicographic_s" + "tart\030\n \001(\tB\003\340A\001\022\036\n\021lexicographic_end\030\013 \001" - + "(\tB\003\340A\001\022\031\n\014soft_deleted\030\014 \001(\010B\003\340A\001\022\027\n\nma" - + "tch_glob\030\016 \001(\tB\003\340A\001B\014\n\n_read_mask\"\205\001\n\027Qu" - + "eryWriteStatusRequest\022\026\n\tupload_id\030\001 \001(\t" - + "B\003\340A\002\022R\n\034common_object_request_params\030\002 " - + "\001(\0132,.google.storage.v2.CommonObjectRequ" - + "estParams\"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\014write_" - + "status\"\250\n\n\024RewriteObjectRequest\022 \n\020desti" - + "nation_name\030\030 \001(\tB\006\340A\002\340A\005\022D\n\022destination" - + "_bucket\030\031 \001(\tB(\340A\002\340A\005\372A\037\n\035storage.google" - + "apis.com/Bucket\022C\n\023destination_kms_key\030\033" - + " \001(\tB&\372A#\n!cloudkms.googleapis.com/Crypt" - + "oKey\022.\n\013destination\030\001 \001(\0132\031.google.stora" - + "ge.v2.Object\022<\n\rsource_bucket\030\002 \001(\tB%\340A\002" - + "\372A\037\n\035storage.googleapis.com/Bucket\022\032\n\rso" - + "urce_object\030\003 \001(\tB\003\340A\002\022\031\n\021source_generat" - + "ion\030\004 \001(\003\022\025\n\rrewrite_token\030\005 \001(\t\022\"\n\032dest" - + "ination_predefined_acl\030\034 \001(\t\022 \n\023if_gener" - + "ation_match\030\007 \001(\003H\000\210\001\001\022$\n\027if_generation_" - + "not_match\030\010 \001(\003H\001\210\001\001\022$\n\027if_metageneratio" - + "n_match\030\t \001(\003H\002\210\001\001\022(\n\033if_metageneration_" - + "not_match\030\n \001(\003H\003\210\001\001\022\'\n\032if_source_genera" - + "tion_match\030\013 \001(\003H\004\210\001\001\022+\n\036if_source_gener" - + "ation_not_match\030\014 \001(\003H\005\210\001\001\022+\n\036if_source_" - + "metageneration_match\030\r \001(\003H\006\210\001\001\022/\n\"if_so" - + "urce_metageneration_not_match\030\016 \001(\003H\007\210\001\001" - + "\022$\n\034max_bytes_rewritten_per_call\030\017 \001(\003\022(" - + "\n copy_source_encryption_algorithm\030\020 \001(\t" - + "\022(\n copy_source_encryption_key_bytes\030\025 \001" - + "(\014\022/\n\'copy_source_encryption_key_sha256_" - + "bytes\030\026 \001(\014\022R\n\034common_object_request_par" - + "ams\030\023 \001(\0132,.google.storage.v2.CommonObje" - + "ctRequestParams\022<\n\020object_checksums\030\035 \001(" - + "\0132\".google.storage.v2.ObjectChecksumsB\026\n" - + "\024_if_generation_matchB\032\n\030_if_generation_" - + "not_matchB\032\n\030_if_metageneration_matchB\036\n" - + "\034_if_metageneration_not_matchB\035\n\033_if_sou" - + "rce_generation_matchB!\n\037_if_source_gener" - + "ation_not_matchB!\n\037_if_source_metagenera" - + "tion_matchB%\n#_if_source_metageneration_" - + "not_match\"\227\001\n\017RewriteResponse\022\035\n\025total_b" - + "ytes_rewritten\030\001 \001(\003\022\023\n\013object_size\030\002 \001(" - + "\003\022\014\n\004done\030\003 \001(\010\022\025\n\rrewrite_token\030\004 \001(\t\022+" - + "\n\010resource\030\005 \001(\0132\031.google.storage.v2.Obj" - + "ect\"\362\001\n\032StartResumableWriteRequest\022B\n\021wr" - + "ite_object_spec\030\001 \001(\0132\".google.storage.v" - + "2.WriteObjectSpecB\003\340A\002\022R\n\034common_object_" - + "request_params\030\003 \001(\0132,.google.storage.v2" - + ".CommonObjectRequestParams\022<\n\020object_che" - + "cksums\030\005 \001(\0132\".google.storage.v2.ObjectC" - + "hecksums\"0\n\033StartResumableWriteResponse\022" - + "\021\n\tupload_id\030\001 \001(\t\"\357\003\n\023UpdateObjectReque" - + "st\022.\n\006object\030\001 \001(\0132\031.google.storage.v2.O" - + "bjectB\003\340A\002\022 \n\023if_generation_match\030\002 \001(\003H" - + "\000\210\001\001\022$\n\027if_generation_not_match\030\003 \001(\003H\001\210" - + "\001\001\022$\n\027if_metageneration_match\030\004 \001(\003H\002\210\001\001" - + "\022(\n\033if_metageneration_not_match\030\005 \001(\003H\003\210" - + "\001\001\022\026\n\016predefined_acl\030\n \001(\t\0224\n\013update_mas" - + "k\030\007 \001(\0132\032.google.protobuf.FieldMaskB\003\340A\002" - + "\022R\n\034common_object_request_params\030\010 \001(\0132," - + ".google.storage.v2.CommonObjectRequestPa" - + "ramsB\026\n\024_if_generation_matchB\032\n\030_if_gene" - + "ration_not_matchB\032\n\030_if_metageneration_m" - + "atchB\036\n\034_if_metageneration_not_match\"`\n\030" - + "GetServiceAccountRequest\022D\n\007project\030\001 \001(" - + "\tB3\340A\002\372A-\n+cloudresourcemanager.googleap" - + "is.com/Project\"\200\001\n\024CreateHmacKeyRequest\022" - + "D\n\007project\030\001 \001(\tB3\340A\002\372A-\n+cloudresourcem" - + "anager.googleapis.com/Project\022\"\n\025service" - + "_account_email\030\002 \001(\tB\003\340A\002\"g\n\025CreateHmacK" - + "eyResponse\0224\n\010metadata\030\001 \001(\0132\".google.st" - + "orage.v2.HmacKeyMetadata\022\030\n\020secret_key_b" - + "ytes\030\003 \001(\014\"t\n\024DeleteHmacKeyRequest\022\026\n\tac" - + "cess_id\030\001 \001(\tB\003\340A\002\022D\n\007project\030\002 \001(\tB3\340A\002" - + "\372A-\n+cloudresourcemanager.googleapis.com" - + "/Project\"q\n\021GetHmacKeyRequest\022\026\n\taccess_" - + "id\030\001 \001(\tB\003\340A\002\022D\n\007project\030\002 \001(\tB3\340A\002\372A-\n+" - + "cloudresourcemanager.googleapis.com/Proj" - + "ect\"\274\001\n\023ListHmacKeysRequest\022D\n\007project\030\001" - + " \001(\tB3\340A\002\372A-\n+cloudresourcemanager.googl" - + "eapis.com/Project\022\021\n\tpage_size\030\002 \001(\005\022\022\n\n" - + "page_token\030\003 \001(\t\022\035\n\025service_account_emai" - + "l\030\004 \001(\t\022\031\n\021show_deleted_keys\030\005 \001(\010\"f\n\024Li" - + "stHmacKeysResponse\0225\n\thmac_keys\030\001 \003(\0132\"." - + "google.storage.v2.HmacKeyMetadata\022\027\n\017nex" - + "t_page_token\030\002 \001(\t\"\202\001\n\024UpdateHmacKeyRequ" - + "est\0229\n\010hmac_key\030\001 \001(\0132\".google.storage.v" - + "2.HmacKeyMetadataB\003\340A\002\022/\n\013update_mask\030\003 " - + "\001(\0132\032.google.protobuf.FieldMask\"|\n\031Commo" - + "nObjectRequestParams\022\034\n\024encryption_algor" - + "ithm\030\001 \001(\t\022\034\n\024encryption_key_bytes\030\004 \001(\014" - + "\022#\n\033encryption_key_sha256_bytes\030\005 \001(\014\"\312\005" - + "\n\020ServiceConstants\"\265\005\n\006Values\022\026\n\022VALUES_" - + "UNSPECIFIED\020\000\022\033\n\024MAX_READ_CHUNK_BYTES\020\200\200" - + "\200\001\022\034\n\025MAX_WRITE_CHUNK_BYTES\020\200\200\200\001\022\031\n\022MAX_" - + "OBJECT_SIZE_MB\020\200\200\300\002\022)\n$MAX_CUSTOM_METADA" - + "TA_FIELD_NAME_BYTES\020\200\010\022*\n%MAX_CUSTOM_MET" - + "ADATA_FIELD_VALUE_BYTES\020\200 \022)\n$MAX_CUSTOM" - + "_METADATA_TOTAL_SIZE_BYTES\020\200@\022*\n$MAX_BUC" - + "KET_METADATA_TOTAL_SIZE_BYTES\020\200\240\001\022\'\n#MAX" - + "_NOTIFICATION_CONFIGS_PER_BUCKET\020d\022\"\n\036MA" - + "X_LIFECYCLE_RULES_PER_BUCKET\020d\022&\n\"MAX_NO" - + "TIFICATION_CUSTOM_ATTRIBUTES\020\005\0221\n,MAX_NO" - + "TIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH\020\200" - + "\002\0223\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE_V" - + "ALUE_LENGTH\020\200\010\022\034\n\030MAX_LABELS_ENTRIES_COU" - + "NT\020@\022\037\n\033MAX_LABELS_KEY_VALUE_LENGTH\020?\022\037\n" - + "\032MAX_LABELS_KEY_VALUE_BYTES\020\200\001\022.\n)MAX_OB" - + "JECT_IDS_PER_DELETE_OBJECTS_REQUEST\020\350\007\022\036" - + "\n\032SPLIT_TOKEN_MAX_VALID_DAYS\020\016\032\002\020\001\"\215\033\n\006B" - + "ucket\022\021\n\004name\030\001 \001(\tB\003\340A\005\022\026\n\tbucket_id\030\002 " - + "\001(\tB\003\340A\003\022\014\n\004etag\030\035 \001(\t\022D\n\007project\030\003 \001(\tB" - + "3\340A\005\372A-\n+cloudresourcemanager.googleapis" - + ".com/Project\022\033\n\016metageneration\030\004 \001(\003B\003\340A" - + "\003\022\025\n\010location\030\005 \001(\tB\003\340A\005\022\032\n\rlocation_typ" - + "e\030\006 \001(\tB\003\340A\003\022\025\n\rstorage_class\030\007 \001(\t\022\013\n\003r" - + "po\030\033 \001(\t\0223\n\003acl\030\010 \003(\0132&.google.storage.v" - + "2.BucketAccessControl\022B\n\022default_object_" - + "acl\030\t \003(\0132&.google.storage.v2.ObjectAcce" - + "ssControl\0226\n\tlifecycle\030\n \001(\0132#.google.st" - + "orage.v2.Bucket.Lifecycle\0224\n\013create_time" - + "\030\013 \001(\0132\032.google.protobuf.TimestampB\003\340A\003\022" - + ",\n\004cors\030\014 \003(\0132\036.google.storage.v2.Bucket" - + ".Cors\0224\n\013update_time\030\r \001(\0132\032.google.prot" - + "obuf.TimestampB\003\340A\003\022 \n\030default_event_bas" - + "ed_hold\030\016 \001(\010\0225\n\006labels\030\017 \003(\0132%.google.s" - + "torage.v2.Bucket.LabelsEntry\0222\n\007website\030" - + "\020 \001(\0132!.google.storage.v2.Bucket.Website" - + "\0228\n\nversioning\030\021 \001(\0132$.google.storage.v2" - + ".Bucket.Versioning\0222\n\007logging\030\022 \001(\0132!.go" - + "ogle.storage.v2.Bucket.Logging\022,\n\005owner\030" - + "\023 \001(\0132\030.google.storage.v2.OwnerB\003\340A\003\0228\n\n" - + "encryption\030\024 \001(\0132$.google.storage.v2.Buc" - + "ket.Encryption\0222\n\007billing\030\025 \001(\0132!.google" - + ".storage.v2.Bucket.Billing\022C\n\020retention_" - + "policy\030\026 \001(\0132).google.storage.v2.Bucket." - + "RetentionPolicy\0227\n\niam_config\030\027 \001(\0132#.go" - + "ogle.storage.v2.Bucket.IamConfig\022\025\n\rsati" - + "sfies_pzs\030\031 \001(\010\022P\n\027custom_placement_conf" - + "ig\030\032 \001(\0132/.google.storage.v2.Bucket.Cust" - + "omPlacementConfig\0226\n\tautoclass\030\034 \001(\0132#.g" - + "oogle.storage.v2.Bucket.Autoclass\022K\n\022sof" - + "t_delete_policy\030\037 \001(\0132*.google.storage.v" - + "2.Bucket.SoftDeletePolicyB\003\340A\001\032!\n\007Billin" - + "g\022\026\n\016requester_pays\030\001 \001(\010\032X\n\004Cors\022\016\n\006ori" - + "gin\030\001 \003(\t\022\016\n\006method\030\002 \003(\t\022\027\n\017response_he" - + "ader\030\003 \003(\t\022\027\n\017max_age_seconds\030\004 \001(\005\032M\n\nE" - + "ncryption\022?\n\017default_kms_key\030\001 \001(\tB&\372A#\n" - + "!cloudkms.googleapis.com/CryptoKey\032\354\001\n\tI" - + "amConfig\022a\n\033uniform_bucket_level_access\030" - + "\001 \001(\0132<.google.storage.v2.Bucket.IamConf" - + "ig.UniformBucketLevelAccess\022 \n\030public_ac" - + "cess_prevention\030\003 \001(\t\032Z\n\030UniformBucketLe" - + "velAccess\022\017\n\007enabled\030\001 \001(\010\022-\n\tlock_time\030" - + "\002 \001(\0132\032.google.protobuf.Timestamp\032\363\005\n\tLi" - + "fecycle\0226\n\004rule\030\001 \003(\0132(.google.storage.v" - + "2.Bucket.Lifecycle.Rule\032\255\005\n\004Rule\022?\n\006acti" - + "on\030\001 \001(\0132/.google.storage.v2.Bucket.Life" - + "cycle.Rule.Action\022E\n\tcondition\030\002 \001(\01322.g" - + "oogle.storage.v2.Bucket.Lifecycle.Rule.C" - + "ondition\032-\n\006Action\022\014\n\004type\030\001 \001(\t\022\025\n\rstor" - + "age_class\030\002 \001(\t\032\355\003\n\tCondition\022\025\n\010age_day" - + "s\030\001 \001(\005H\000\210\001\001\022)\n\016created_before\030\002 \001(\0132\021.g" - + "oogle.type.Date\022\024\n\007is_live\030\003 \001(\010H\001\210\001\001\022\037\n" - + "\022num_newer_versions\030\004 \001(\005H\002\210\001\001\022\035\n\025matche" - + "s_storage_class\030\005 \003(\t\022#\n\026days_since_cust" - + "om_time\030\007 \001(\005H\003\210\001\001\022-\n\022custom_time_before" - + "\030\010 \001(\0132\021.google.type.Date\022\'\n\032days_since_" - + "noncurrent_time\030\t \001(\005H\004\210\001\001\0221\n\026noncurrent" - + "_time_before\030\n \001(\0132\021.google.type.Date\022\026\n" - + "\016matches_prefix\030\013 \003(\t\022\026\n\016matches_suffix\030" - + "\014 \003(\tB\013\n\t_age_daysB\n\n\010_is_liveB\025\n\023_num_n" - + "ewer_versionsB\031\n\027_days_since_custom_time" - + "B\035\n\033_days_since_noncurrent_time\0328\n\007Loggi" - + "ng\022\022\n\nlog_bucket\030\001 \001(\t\022\031\n\021log_object_pre" - + "fix\030\002 \001(\t\032\217\001\n\017RetentionPolicy\0222\n\016effecti" - + "ve_time\030\001 \001(\0132\032.google.protobuf.Timestam" - + "p\022\021\n\tis_locked\030\002 \001(\010\0225\n\022retention_durati" - + "on\030\004 \001(\0132\031.google.protobuf.Duration\032\261\001\n\020" - + "SoftDeletePolicy\022:\n\022retention_duration\030\001" - + " \001(\0132\031.google.protobuf.DurationH\000\210\001\001\0227\n\016" - + "effective_time\030\002 \001(\0132\032.google.protobuf.T" - + "imestampH\001\210\001\001B\025\n\023_retention_durationB\021\n\017" - + "_effective_time\032\035\n\nVersioning\022\017\n\007enabled" - + "\030\001 \001(\010\032;\n\007Website\022\030\n\020main_page_suffix\030\001 " - + "\001(\t\022\026\n\016not_found_page\030\002 \001(\t\032/\n\025CustomPla" - + "cementConfig\022\026\n\016data_locations\030\001 \003(\t\032\213\002\n" - + "\tAutoclass\022\017\n\007enabled\030\001 \001(\010\0224\n\013toggle_ti" - + "me\030\002 \001(\0132\032.google.protobuf.TimestampB\003\340A" - + "\003\022#\n\026terminal_storage_class\030\003 \001(\tH\000\210\001\001\022P" - + "\n\"terminal_storage_class_update_time\030\004 \001" - + "(\0132\032.google.protobuf.TimestampB\003\340A\003H\001\210\001\001" - + "B\031\n\027_terminal_storage_classB%\n#_terminal" - + "_storage_class_update_time\032-\n\013LabelsEntr" - + "y\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001:G\352AD\n\035" - + "storage.googleapis.com/Bucket\022#projects/" - + "{project}/buckets/{bucket}\"\316\001\n\023BucketAcc" - + "essControl\022\014\n\004role\030\001 \001(\t\022\n\n\002id\030\002 \001(\t\022\016\n\006" - + "entity\030\003 \001(\t\022\027\n\nentity_alt\030\t \001(\tB\003\340A\003\022\021\n" - + "\tentity_id\030\004 \001(\t\022\014\n\004etag\030\010 \001(\t\022\r\n\005email\030" - + "\005 \001(\t\022\016\n\006domain\030\006 \001(\t\0224\n\014project_team\030\007 " - + "\001(\0132\036.google.storage.v2.ProjectTeam\"I\n\017C" - + "hecksummedData\022\026\n\007content\030\001 \001(\014B\005\010\001\340A\001\022\023" - + "\n\006crc32c\030\002 \001(\007H\000\210\001\001B\t\n\007_crc32c\"C\n\017Object" - + "Checksums\022\023\n\006crc32c\030\001 \001(\007H\000\210\001\001\022\020\n\010md5_ha" - + "sh\030\002 \001(\014B\t\n\007_crc32c\"\255\002\n\017HmacKeyMetadata\022" - + "\017\n\002id\030\001 \001(\tB\003\340A\005\022\026\n\taccess_id\030\002 \001(\tB\003\340A\005" - + "\022D\n\007project\030\003 \001(\tB3\340A\005\372A-\n+cloudresource" - + "manager.googleapis.com/Project\022\"\n\025servic" - + "e_account_email\030\004 \001(\tB\003\340A\003\022\r\n\005state\030\005 \001(" - + "\t\0224\n\013create_time\030\006 \001(\0132\032.google.protobuf" - + ".TimestampB\003\340A\003\0224\n\013update_time\030\007 \001(\0132\032.g", - "oogle.protobuf.TimestampB\003\340A\003\022\014\n\004etag\030\010 " - + "\001(\t\"\247\003\n\022NotificationConfig\022\021\n\004name\030\001 \001(\t" - + "B\003\340A\002\022\022\n\005topic\030\002 \001(\tB\003\340A\002\022\014\n\004etag\030\007 \001(\t\022" - + "\023\n\013event_types\030\003 \003(\t\022V\n\021custom_attribute" - + "s\030\004 \003(\0132;.google.storage.v2.Notification" - + "Config.CustomAttributesEntry\022\032\n\022object_n" - + "ame_prefix\030\005 \001(\t\022\033\n\016payload_format\030\006 \001(\t" - + "B\003\340A\002\0327\n\025CustomAttributesEntry\022\013\n\003key\030\001 " - + "\001(\t\022\r\n\005value\030\002 \001(\t:\0028\001:}\352Az\n)storage.goo" - + "gleapis.com/NotificationConfig\022Mprojects" - + "/{project}/buckets/{bucket}/notification" - + "Configs/{notification_config}\"L\n\022Custome" - + "rEncryption\022\034\n\024encryption_algorithm\030\001 \001(" - + "\t\022\030\n\020key_sha256_bytes\030\003 \001(\014\"\254\n\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\014\n\004etag" - + "\030\033 \001(\t\022\027\n\ngeneration\030\003 \001(\003B\003\340A\005\022\033\n\016metag" - + "eneration\030\004 \001(\003B\003\340A\003\022\025\n\rstorage_class\030\005 " - + "\001(\t\022\021\n\004size\030\006 \001(\003B\003\340A\003\022\030\n\020content_encodi" - + "ng\030\007 \001(\t\022\033\n\023content_disposition\030\010 \001(\t\022\025\n" - + "\rcache_control\030\t \001(\t\0223\n\003acl\030\n \003(\0132&.goog" - + "le.storage.v2.ObjectAccessControl\022\030\n\020con" - + "tent_language\030\013 \001(\t\0224\n\013delete_time\030\014 \001(\013" - + "2\032.google.protobuf.TimestampB\003\340A\003\022\024\n\014con" - + "tent_type\030\r \001(\t\0224\n\013create_time\030\016 \001(\0132\032.g" - + "oogle.protobuf.TimestampB\003\340A\003\022\034\n\017compone" - + "nt_count\030\017 \001(\005B\003\340A\003\022:\n\tchecksums\030\020 \001(\0132\"" - + ".google.storage.v2.ObjectChecksumsB\003\340A\003\022" - + "4\n\013update_time\030\021 \001(\0132\032.google.protobuf.T" - + "imestampB\003\340A\003\0227\n\007kms_key\030\022 \001(\tB&\372A#\n!clo" - + "udkms.googleapis.com/CryptoKey\022B\n\031update" - + "_storage_class_time\030\023 \001(\0132\032.google.proto" - + "buf.TimestampB\003\340A\003\022\026\n\016temporary_hold\030\024 \001" - + "(\010\0229\n\025retention_expire_time\030\025 \001(\0132\032.goog" - + "le.protobuf.Timestamp\0229\n\010metadata\030\026 \003(\0132" - + "\'.google.storage.v2.Object.MetadataEntry" - + "\022\035\n\020event_based_hold\030\027 \001(\010H\000\210\001\001\022,\n\005owner" - + "\030\030 \001(\0132\030.google.storage.v2.OwnerB\003\340A\003\022B\n" - + "\023customer_encryption\030\031 \001(\0132%.google.stor" - + "age.v2.CustomerEncryption\022/\n\013custom_time" - + "\030\032 \001(\0132\032.google.protobuf.Timestamp\022>\n\020so" - + "ft_delete_time\030\034 \001(\0132\032.google.protobuf.T" - + "imestampB\003\340A\003H\001\210\001\001\022>\n\020hard_delete_time\030\035" - + " \001(\0132\032.google.protobuf.TimestampB\003\340A\003H\002\210" - + "\001\001\032/\n\rMetadataEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005valu" - + "e\030\002 \001(\t:\0028\001B\023\n\021_event_based_holdB\023\n\021_sof" - + "t_delete_timeB\023\n\021_hard_delete_time\"\316\001\n\023O" - + "bjectAccessControl\022\014\n\004role\030\001 \001(\t\022\n\n\002id\030\002" - + " \001(\t\022\016\n\006entity\030\003 \001(\t\022\027\n\nentity_alt\030\t \001(\t" - + "B\003\340A\003\022\021\n\tentity_id\030\004 \001(\t\022\014\n\004etag\030\010 \001(\t\022\r" - + "\n\005email\030\005 \001(\t\022\016\n\006domain\030\006 \001(\t\0224\n\014project" - + "_team\030\007 \001(\0132\036.google.storage.v2.ProjectT" - + "eam\"l\n\023ListObjectsResponse\022*\n\007objects\030\001 " - + "\003(\0132\031.google.storage.v2.Object\022\020\n\010prefix" - + "es\030\002 \003(\t\022\027\n\017next_page_token\030\003 \001(\t\"3\n\013Pro" - + "jectTeam\022\026\n\016project_number\030\001 \001(\t\022\014\n\004team" - + "\030\002 \001(\t\"\'\n\016ServiceAccount\022\025\n\remail_addres" - + "s\030\001 \001(\t\"*\n\005Owner\022\016\n\006entity\030\001 \001(\t\022\021\n\tenti" - + "ty_id\030\002 \001(\t\"C\n\014ContentRange\022\r\n\005start\030\001 \001" - + "(\003\022\013\n\003end\030\002 \001(\003\022\027\n\017complete_length\030\003 \001(\003" - + "2\252\'\n\007Storage\022r\n\014DeleteBucket\022&.google.st" - + "orage.v2.DeleteBucketRequest\032\026.google.pr" - + "otobuf.Empty\"\"\332A\004name\212\323\344\223\002\025\022\023\n\004name\022\013{bu" - + "cket=**}\022o\n\tGetBucket\022#.google.storage.v" - + "2.GetBucketRequest\032\031.google.storage.v2.B" - + "ucket\"\"\332A\004name\212\323\344\223\002\025\022\023\n\004name\022\013{bucket=**" - + "}\022\253\001\n\014CreateBucket\022&.google.storage.v2.C" - + "reateBucketRequest\032\031.google.storage.v2.B" - + "ucket\"X\332A\027parent,bucket,bucket_id\212\323\344\223\0028\022" - + "\026\n\006parent\022\014{project=**}\022\036\n\016bucket.projec" - + "t\022\014{project=**}\022\205\001\n\013ListBuckets\022%.google" - + ".storage.v2.ListBucketsRequest\032&.google." - + "storage.v2.ListBucketsResponse\"\'\332A\006paren" - + "t\212\323\344\223\002\030\022\026\n\006parent\022\014{project=**}\022\223\001\n\031Lock" - + "BucketRetentionPolicy\0223.google.storage.v" - + "2.LockBucketRetentionPolicyRequest\032\031.goo" - + "gle.storage.v2.Bucket\"&\332A\006bucket\212\323\344\223\002\027\022\025" - + "\n\006bucket\022\013{bucket=**}\022u\n\014GetIamPolicy\022\"." - + "google.iam.v1.GetIamPolicyRequest\032\025.goog" - + "le.iam.v1.Policy\"*\332A\010resource\212\323\344\223\002\031\022\027\n\010r" - + "esource\022\013{bucket=**}\022|\n\014SetIamPolicy\022\".g" - + "oogle.iam.v1.SetIamPolicyRequest\032\025.googl" - + "e.iam.v1.Policy\"1\332A\017resource,policy\212\323\344\223\002" - + "\031\022\027\n\010resource\022\013{bucket=**}\022\327\001\n\022TestIamPe" - + "rmissions\022(.google.iam.v1.TestIamPermiss" - + "ionsRequest\032).google.iam.v1.TestIamPermi" - + "ssionsResponse\"l\332A\024resource,permissions\212" - + "\323\344\223\002O\022\027\n\010resource\022\013{bucket=**}\0224\n\010resour" - + "ce\022({bucket=projects/*/buckets/*}/object" - + "s/**\022\212\001\n\014UpdateBucket\022&.google.storage.v" - + "2.UpdateBucketRequest\032\031.google.storage.v" - + "2.Bucket\"7\332A\022bucket,update_mask\212\323\344\223\002\034\022\032\n" - + "\013bucket.name\022\013{bucket=**}\022\237\001\n\030DeleteNoti" - + "ficationConfig\0222.google.storage.v2.Delet" - + "eNotificationConfigRequest\032\026.google.prot" - + "obuf.Empty\"7\332A\004name\212\323\344\223\002*\022(\n\004name\022 {buck" - + "et=projects/*/buckets/*}/**\022\250\001\n\025GetNotif" - + "icationConfig\022/.google.storage.v2.GetNot" - + "ificationConfigRequest\032%.google.storage." - + "v2.NotificationConfig\"7\332A\004name\212\323\344\223\002*\022(\n\004" - + "name\022 {bucket=projects/*/buckets/*}/**\022\261" - + "\001\n\030CreateNotificationConfig\0222.google.sto" - + "rage.v2.CreateNotificationConfigRequest\032" - + "%.google.storage.v2.NotificationConfig\":" - + "\332A\032parent,notification_config\212\323\344\223\002\027\022\025\n\006p" - + "arent\022\013{bucket=**}\022\250\001\n\027ListNotificationC" - + "onfigs\0221.google.storage.v2.ListNotificat" - + "ionConfigsRequest\0322.google.storage.v2.Li" - + "stNotificationConfigsResponse\"&\332A\006parent" - + "\212\323\344\223\002\027\022\025\n\006parent\022\013{bucket=**}\022~\n\rCompose" - + "Object\022\'.google.storage.v2.ComposeObject" - + "Request\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.Delet" - + "eObjectRequest\032\026.google.protobuf.Empty\"H" - + "\332A\rbucket,object\332A\030bucket,object,generat" - + "ion\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}\022\215\001\n\rRes" - + "toreObject\022\'.google.storage.v2.RestoreOb" - + "jectRequest\032\031.google.storage.v2.Object\"8" - + "\332A\030bucket,object,generation\212\323\344\223\002\027\022\025\n\006buc" - + "ket\022\013{bucket=**}\022\272\001\n\024CancelResumableWrit" - + "e\022..google.storage.v2.CancelResumableWri" - + "teRequest\032/.google.storage.v2.CancelResu" - + "mableWriteResponse\"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." - + "GetObjectRequest\032\031.google.storage.v2.Obj" - + "ect\"H\332A\rbucket,object\332A\030bucket,object,ge" - + "neration\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}\022\245\001" - + "\n\nReadObject\022$.google.storage.v2.ReadObj" - + "ectRequest\032%.google.storage.v2.ReadObjec" - + "tResponse\"H\332A\rbucket,object\332A\030bucket,obj" - + "ect,generation\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=" - + "**}0\001\022\214\001\n\014UpdateObject\022&.google.storage." - + "v2.UpdateObjectRequest\032\031.google.storage." - + "v2.Object\"9\332A\022object,update_mask\212\323\344\223\002\036\022\034" - + "\n\robject.bucket\022\013{bucket=**}\022`\n\013WriteObj" - + "ect\022%.google.storage.v2.WriteObjectReque" - + "st\032&.google.storage.v2.WriteObjectRespon" - + "se\"\000(\001\022n\n\017BidiWriteObject\022).google.stora" - + "ge.v2.BidiWriteObjectRequest\032*.google.st" - + "orage.v2.BidiWriteObjectResponse\"\000(\0010\001\022\204" - + "\001\n\013ListObjects\022%.google.storage.v2.ListO" - + "bjectsRequest\032&.google.storage.v2.ListOb" - + "jectsResponse\"&\332A\006parent\212\323\344\223\002\027\022\025\n\006parent" - + "\022\013{bucket=**}\022\230\001\n\rRewriteObject\022\'.google" - + ".storage.v2.RewriteObjectRequest\032\".googl" - + "e.storage.v2.RewriteResponse\":\212\323\344\223\0024\022\017\n\r" - + "source_bucket\022!\n\022destination_bucket\022\013{bu" - + "cket=**}\022\256\001\n\023StartResumableWrite\022-.googl" - + "e.storage.v2.StartResumableWriteRequest\032" - + "..google.storage.v2.StartResumableWriteR" - + "esponse\"8\212\323\344\223\0022\0220\n!write_object_spec.res" - + "ource.bucket\022\013{bucket=**}\022\256\001\n\020QueryWrite" - + "Status\022*.google.storage.v2.QueryWriteSta" - + "tusRequest\032+.google.storage.v2.QueryWrit" - + "eStatusResponse\"A\332A\tupload_id\212\323\344\223\002/\022-\n\tu" - + "pload_id\022 {bucket=projects/*/buckets/*}/" - + "**\022\200\001\n\021GetServiceAccount\022+.google.storag" - + "e.v2.GetServiceAccountRequest\032!.google.s" - + "torage.v2.ServiceAccount\"\033\332A\007project\212\323\344\223" - + "\002\013\022\t\n\007project\022\225\001\n\rCreateHmacKey\022\'.google" - + ".storage.v2.CreateHmacKeyRequest\032(.googl" - + "e.storage.v2.CreateHmacKeyResponse\"1\332A\035p" - + "roject,service_account_email\212\323\344\223\002\013\022\t\n\007pr" - + "oject\022w\n\rDeleteHmacKey\022\'.google.storage." - + "v2.DeleteHmacKeyRequest\032\026.google.protobu" - + "f.Empty\"%\332A\021access_id,project\212\323\344\223\002\013\022\t\n\007p" - + "roject\022}\n\nGetHmacKey\022$.google.storage.v2" - + ".GetHmacKeyRequest\032\".google.storage.v2.H" - + "macKeyMetadata\"%\332A\021access_id,project\212\323\344\223" - + "\002\013\022\t\n\007project\022|\n\014ListHmacKeys\022&.google.s" - + "torage.v2.ListHmacKeysRequest\032\'.google.s" - + "torage.v2.ListHmacKeysResponse\"\033\332A\007proje" - + "ct\212\323\344\223\002\013\022\t\n\007project\022\235\001\n\rUpdateHmacKey\022\'." - + "google.storage.v2.UpdateHmacKeyRequest\032\"" - + ".google.storage.v2.HmacKeyMetadata\"?\332A\024h" - + "mac_key,update_mask\212\323\344\223\002\"\022 \n\020hmac_key.pr" - + "oject\022\014{project=**}\032\247\002\312A\026storage.googlea" - + "pis.com\322A\212\002https://www.googleapis.com/au" - + "th/cloud-platform,https://www.googleapis" - + ".com/auth/cloud-platform.read-only,https" - + "://www.googleapis.com/auth/devstorage.fu" - + "ll_control,https://www.googleapis.com/au" - + "th/devstorage.read_only,https://www.goog" - + "leapis.com/auth/devstorage.read_writeB\342\001" - + "\n\025com.google.storage.v2B\014StorageProtoP\001Z" - + ">cloud.google.com/go/storage/internal/ap" - + "iv2/storagepb;storagepb\352Ax\n!cloudkms.goo" - + "gleapis.com/CryptoKey\022Sprojects/{project" - + "}/locations/{location}/keyRings/{key_rin" - + "g}/cryptoKeys/{crypto_key}b\006proto3" + + "(\tB\003\340A\001\022\031\n\014soft_deleted\030\014 \001(\010B\003\340A\001\022(\n\033in" + + "clude_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_read_mask\"\205\001\n\027" + + "QueryWriteStatusRequest\022\026\n\tupload_id\030\001 \001" + + "(\tB\003\340A\002\022R\n\034common_object_request_params\030" + + "\002 \001(\0132,.google.storage.v2.CommonObjectRe" + + "questParams\"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\014writ" + + "e_status\"\250\n\n\024RewriteObjectRequest\022 \n\020des" + + "tination_name\030\030 \001(\tB\006\340A\002\340A\005\022D\n\022destinati" + + "on_bucket\030\031 \001(\tB(\340A\002\340A\005\372A\037\n\035storage.goog" + + "leapis.com/Bucket\022C\n\023destination_kms_key" + + "\030\033 \001(\tB&\372A#\n!cloudkms.googleapis.com/Cry" + + "ptoKey\022.\n\013destination\030\001 \001(\0132\031.google.sto" + + "rage.v2.Object\022<\n\rsource_bucket\030\002 \001(\tB%\340" + + "A\002\372A\037\n\035storage.googleapis.com/Bucket\022\032\n\r" + + "source_object\030\003 \001(\tB\003\340A\002\022\031\n\021source_gener" + + "ation\030\004 \001(\003\022\025\n\rrewrite_token\030\005 \001(\t\022\"\n\032de" + + "stination_predefined_acl\030\034 \001(\t\022 \n\023if_gen" + + "eration_match\030\007 \001(\003H\000\210\001\001\022$\n\027if_generatio" + + "n_not_match\030\010 \001(\003H\001\210\001\001\022$\n\027if_metagenerat" + + "ion_match\030\t \001(\003H\002\210\001\001\022(\n\033if_metageneratio" + + "n_not_match\030\n \001(\003H\003\210\001\001\022\'\n\032if_source_gene" + + "ration_match\030\013 \001(\003H\004\210\001\001\022+\n\036if_source_gen" + + "eration_not_match\030\014 \001(\003H\005\210\001\001\022+\n\036if_sourc" + + "e_metageneration_match\030\r \001(\003H\006\210\001\001\022/\n\"if_" + + "source_metageneration_not_match\030\016 \001(\003H\007\210" + + "\001\001\022$\n\034max_bytes_rewritten_per_call\030\017 \001(\003" + + "\022(\n copy_source_encryption_algorithm\030\020 \001" + + "(\t\022(\n copy_source_encryption_key_bytes\030\025" + + " \001(\014\022/\n\'copy_source_encryption_key_sha25" + + "6_bytes\030\026 \001(\014\022R\n\034common_object_request_p" + + "arams\030\023 \001(\0132,.google.storage.v2.CommonOb" + + "jectRequestParams\022<\n\020object_checksums\030\035 " + + "\001(\0132\".google.storage.v2.ObjectChecksumsB" + + "\026\n\024_if_generation_matchB\032\n\030_if_generatio" + + "n_not_matchB\032\n\030_if_metageneration_matchB" + + "\036\n\034_if_metageneration_not_matchB\035\n\033_if_s" + + "ource_generation_matchB!\n\037_if_source_gen" + + "eration_not_matchB!\n\037_if_source_metagene" + + "ration_matchB%\n#_if_source_metageneratio" + + "n_not_match\"\227\001\n\017RewriteResponse\022\035\n\025total" + + "_bytes_rewritten\030\001 \001(\003\022\023\n\013object_size\030\002 " + + "\001(\003\022\014\n\004done\030\003 \001(\010\022\025\n\rrewrite_token\030\004 \001(\t" + + "\022+\n\010resource\030\005 \001(\0132\031.google.storage.v2.O" + + "bject\"\362\001\n\032StartResumableWriteRequest\022B\n\021" + + "write_object_spec\030\001 \001(\0132\".google.storage" + + ".v2.WriteObjectSpecB\003\340A\002\022R\n\034common_objec" + + "t_request_params\030\003 \001(\0132,.google.storage." + + "v2.CommonObjectRequestParams\022<\n\020object_c" + + "hecksums\030\005 \001(\0132\".google.storage.v2.Objec" + + "tChecksums\"0\n\033StartResumableWriteRespons" + + "e\022\021\n\tupload_id\030\001 \001(\t\"\357\003\n\023UpdateObjectReq" + + "uest\022.\n\006object\030\001 \001(\0132\031.google.storage.v2" + + ".ObjectB\003\340A\002\022 \n\023if_generation_match\030\002 \001(" + + "\003H\000\210\001\001\022$\n\027if_generation_not_match\030\003 \001(\003H" + + "\001\210\001\001\022$\n\027if_metageneration_match\030\004 \001(\003H\002\210" + + "\001\001\022(\n\033if_metageneration_not_match\030\005 \001(\003H" + + "\003\210\001\001\022\026\n\016predefined_acl\030\n \001(\t\0224\n\013update_m" + + "ask\030\007 \001(\0132\032.google.protobuf.FieldMaskB\003\340" + + "A\002\022R\n\034common_object_request_params\030\010 \001(\013" + + "2,.google.storage.v2.CommonObjectRequest" + + "ParamsB\026\n\024_if_generation_matchB\032\n\030_if_ge" + + "neration_not_matchB\032\n\030_if_metageneration" + + "_matchB\036\n\034_if_metageneration_not_match\"`" + + "\n\030GetServiceAccountRequest\022D\n\007project\030\001 " + + "\001(\tB3\340A\002\372A-\n+cloudresourcemanager.google" + + "apis.com/Project\"\200\001\n\024CreateHmacKeyReques" + + "t\022D\n\007project\030\001 \001(\tB3\340A\002\372A-\n+cloudresourc" + + "emanager.googleapis.com/Project\022\"\n\025servi" + + "ce_account_email\030\002 \001(\tB\003\340A\002\"g\n\025CreateHma" + + "cKeyResponse\0224\n\010metadata\030\001 \001(\0132\".google." + + "storage.v2.HmacKeyMetadata\022\030\n\020secret_key" + + "_bytes\030\003 \001(\014\"t\n\024DeleteHmacKeyRequest\022\026\n\t" + + "access_id\030\001 \001(\tB\003\340A\002\022D\n\007project\030\002 \001(\tB3\340" + + "A\002\372A-\n+cloudresourcemanager.googleapis.c" + + "om/Project\"q\n\021GetHmacKeyRequest\022\026\n\tacces" + + "s_id\030\001 \001(\tB\003\340A\002\022D\n\007project\030\002 \001(\tB3\340A\002\372A-" + + "\n+cloudresourcemanager.googleapis.com/Pr" + + "oject\"\274\001\n\023ListHmacKeysRequest\022D\n\007project" + + "\030\001 \001(\tB3\340A\002\372A-\n+cloudresourcemanager.goo" + + "gleapis.com/Project\022\021\n\tpage_size\030\002 \001(\005\022\022" + + "\n\npage_token\030\003 \001(\t\022\035\n\025service_account_em" + + "ail\030\004 \001(\t\022\031\n\021show_deleted_keys\030\005 \001(\010\"f\n\024" + + "ListHmacKeysResponse\0225\n\thmac_keys\030\001 \003(\0132" + + "\".google.storage.v2.HmacKeyMetadata\022\027\n\017n" + + "ext_page_token\030\002 \001(\t\"\202\001\n\024UpdateHmacKeyRe" + + "quest\0229\n\010hmac_key\030\001 \001(\0132\".google.storage" + + ".v2.HmacKeyMetadataB\003\340A\002\022/\n\013update_mask\030" + + "\003 \001(\0132\032.google.protobuf.FieldMask\"|\n\031Com" + + "monObjectRequestParams\022\034\n\024encryption_alg" + + "orithm\030\001 \001(\t\022\034\n\024encryption_key_bytes\030\004 \001" + + "(\014\022#\n\033encryption_key_sha256_bytes\030\005 \001(\014\"" + + "\312\005\n\020ServiceConstants\"\265\005\n\006Values\022\026\n\022VALUE" + + "S_UNSPECIFIED\020\000\022\033\n\024MAX_READ_CHUNK_BYTES\020" + + "\200\200\200\001\022\034\n\025MAX_WRITE_CHUNK_BYTES\020\200\200\200\001\022\031\n\022MA" + + "X_OBJECT_SIZE_MB\020\200\200\300\002\022)\n$MAX_CUSTOM_META" + + "DATA_FIELD_NAME_BYTES\020\200\010\022*\n%MAX_CUSTOM_M" + + "ETADATA_FIELD_VALUE_BYTES\020\200 \022)\n$MAX_CUST" + + "OM_METADATA_TOTAL_SIZE_BYTES\020\200@\022*\n$MAX_B" + + "UCKET_METADATA_TOTAL_SIZE_BYTES\020\200\240\001\022\'\n#M" + + "AX_NOTIFICATION_CONFIGS_PER_BUCKET\020d\022\"\n\036" + + "MAX_LIFECYCLE_RULES_PER_BUCKET\020d\022&\n\"MAX_" + + "NOTIFICATION_CUSTOM_ATTRIBUTES\020\005\0221\n,MAX_" + + "NOTIFICATION_CUSTOM_ATTRIBUTE_KEY_LENGTH" + + "\020\200\002\0223\n.MAX_NOTIFICATION_CUSTOM_ATTRIBUTE" + + "_VALUE_LENGTH\020\200\010\022\034\n\030MAX_LABELS_ENTRIES_C" + + "OUNT\020@\022\037\n\033MAX_LABELS_KEY_VALUE_LENGTH\020?\022" + + "\037\n\032MAX_LABELS_KEY_VALUE_BYTES\020\200\001\022.\n)MAX_" + + "OBJECT_IDS_PER_DELETE_OBJECTS_REQUEST\020\350\007" + + "\022\036\n\032SPLIT_TOKEN_MAX_VALID_DAYS\020\016\032\002\020\001\"\222\034\n" + + "\006Bucket\022\021\n\004name\030\001 \001(\tB\003\340A\005\022\026\n\tbucket_id\030" + + "\002 \001(\tB\003\340A\003\022\014\n\004etag\030\035 \001(\t\022D\n\007project\030\003 \001(" + + "\tB3\340A\005\372A-\n+cloudresourcemanager.googleap" + + "is.com/Project\022\033\n\016metageneration\030\004 \001(\003B\003" + + "\340A\003\022\025\n\010location\030\005 \001(\tB\003\340A\005\022\032\n\rlocation_t" + + "ype\030\006 \001(\tB\003\340A\003\022\025\n\rstorage_class\030\007 \001(\t\022\013\n" + + "\003rpo\030\033 \001(\t\0223\n\003acl\030\010 \003(\0132&.google.storage" + + ".v2.BucketAccessControl\022B\n\022default_objec" + + "t_acl\030\t \003(\0132&.google.storage.v2.ObjectAc" + + "cessControl\0226\n\tlifecycle\030\n \001(\0132#.google." + + "storage.v2.Bucket.Lifecycle\0224\n\013create_ti" + + "me\030\013 \001(\0132\032.google.protobuf.TimestampB\003\340A" + + "\003\022,\n\004cors\030\014 \003(\0132\036.google.storage.v2.Buck" + + "et.Cors\0224\n\013update_time\030\r \001(\0132\032.google.pr" + + "otobuf.TimestampB\003\340A\003\022 \n\030default_event_b" + + "ased_hold\030\016 \001(\010\0225\n\006labels\030\017 \003(\0132%.google" + + ".storage.v2.Bucket.LabelsEntry\0222\n\007websit" + + "e\030\020 \001(\0132!.google.storage.v2.Bucket.Websi" + + "te\0228\n\nversioning\030\021 \001(\0132$.google.storage." + + "v2.Bucket.Versioning\0222\n\007logging\030\022 \001(\0132!." + + "google.storage.v2.Bucket.Logging\022,\n\005owne" + + "r\030\023 \001(\0132\030.google.storage.v2.OwnerB\003\340A\003\0228" + + "\n\nencryption\030\024 \001(\0132$.google.storage.v2.B" + + "ucket.Encryption\0222\n\007billing\030\025 \001(\0132!.goog" + + "le.storage.v2.Bucket.Billing\022C\n\020retentio" + + "n_policy\030\026 \001(\0132).google.storage.v2.Bucke" + + "t.RetentionPolicy\0227\n\niam_config\030\027 \001(\0132#." + + "google.storage.v2.Bucket.IamConfig\022\025\n\rsa" + + "tisfies_pzs\030\031 \001(\010\022P\n\027custom_placement_co" + + "nfig\030\032 \001(\0132/.google.storage.v2.Bucket.Cu" + + "stomPlacementConfig\0226\n\tautoclass\030\034 \001(\0132#" + + ".google.storage.v2.Bucket.Autoclass\022T\n\026h" + + "ierarchical_namespace\030 \001(\0132/.google.sto" + + "rage.v2.Bucket.HierarchicalNamespaceB\003\340A" + + "\001\022K\n\022soft_delete_policy\030\037 \001(\0132*.google.s" + + "torage.v2.Bucket.SoftDeletePolicyB\003\340A\001\032!" + + "\n\007Billing\022\026\n\016requester_pays\030\001 \001(\010\032X\n\004Cor" + + "s\022\016\n\006origin\030\001 \003(\t\022\016\n\006method\030\002 \003(\t\022\027\n\017res" + + "ponse_header\030\003 \003(\t\022\027\n\017max_age_seconds\030\004 " + + "\001(\005\032M\n\nEncryption\022?\n\017default_kms_key\030\001 \001" + + "(\tB&\372A#\n!cloudkms.googleapis.com/CryptoK" + + "ey\032\354\001\n\tIamConfig\022a\n\033uniform_bucket_level" + + "_access\030\001 \001(\0132<.google.storage.v2.Bucket" + + ".IamConfig.UniformBucketLevelAccess\022 \n\030p" + + "ublic_access_prevention\030\003 \001(\t\032Z\n\030Uniform" + + "BucketLevelAccess\022\017\n\007enabled\030\001 \001(\010\022-\n\tlo" + + "ck_time\030\002 \001(\0132\032.google.protobuf.Timestam" + + "p\032\363\005\n\tLifecycle\0226\n\004rule\030\001 \003(\0132(.google.s" + + "torage.v2.Bucket.Lifecycle.Rule\032\255\005\n\004Rule" + + "\022?\n\006action\030\001 \001(\0132/.google.storage.v2.Buc" + + "ket.Lifecycle.Rule.Action\022E\n\tcondition\030\002" + + " \001(\01322.google.storage.v2.Bucket.Lifecycl" + + "e.Rule.Condition\032-\n\006Action\022\014\n\004type\030\001 \001(\t" + + "\022\025\n\rstorage_class\030\002 \001(\t\032\355\003\n\tCondition\022\025\n" + + "\010age_days\030\001 \001(\005H\000\210\001\001\022)\n\016created_before\030\002" + + " \001(\0132\021.google.type.Date\022\024\n\007is_live\030\003 \001(\010" + + "H\001\210\001\001\022\037\n\022num_newer_versions\030\004 \001(\005H\002\210\001\001\022\035" + + "\n\025matches_storage_class\030\005 \003(\t\022#\n\026days_si" + + "nce_custom_time\030\007 \001(\005H\003\210\001\001\022-\n\022custom_tim" + + "e_before\030\010 \001(\0132\021.google.type.Date\022\'\n\032day" + + "s_since_noncurrent_time\030\t \001(\005H\004\210\001\001\0221\n\026no" + + "ncurrent_time_before\030\n \001(\0132\021.google.type" + + ".Date\022\026\n\016matches_prefix\030\013 \003(\t\022\026\n\016matches" + + "_suffix\030\014 \003(\tB\013\n\t_age_daysB\n\n\010_is_liveB\025" + + "\n\023_num_newer_versionsB\031\n\027_days_since_cus" + + "tom_timeB\035\n\033_days_since_noncurrent_time\032" + + "8\n\007Logging\022\022\n\nlog_bucket\030\001 \001(\t\022\031\n\021log_ob" + + "ject_prefix\030\002 \001(\t\032\217\001\n\017RetentionPolicy\0222\n" + + "\016effective_time\030\001 \001(\0132\032.google.protobuf." + + "Timestamp\022\021\n\tis_locked\030\002 \001(\010\0225\n\022retentio" + + "n_duration\030\004 \001(\0132\031.google.protobuf.Durat" + + "ion\032\261\001\n\020SoftDeletePolicy\022:\n\022retention_du" + + "ration\030\001 \001(\0132\031.google.protobuf.DurationH" + + "\000\210\001\001\0227\n\016effective_time\030\002 \001(\0132\032.google.pr" + + "otobuf.TimestampH\001\210\001\001B\025\n\023_retention_dura" + + "tionB\021\n\017_effective_time\032\035\n\nVersioning\022\017\n" + + "\007enabled\030\001 \001(\010\032;\n\007Website\022\030\n\020main_page_s" + + "uffix\030\001 \001(\t\022\026\n\016not_found_page\030\002 \001(\t\032/\n\025C" + + "ustomPlacementConfig\022\026\n\016data_locations\030\001" + + " \003(\t\032\213\002\n\tAutoclass\022\017\n\007enabled\030\001 \001(\010\0224\n\013t" + + "oggle_time\030\002 \001(\0132\032.google.protobuf.Times" + + "tampB\003\340A\003\022#\n\026terminal_storage_class\030\003 \001(" + + "\tH\000\210\001\001\022P\n\"terminal_storage_class_update_" + + "time\030\004 \001(\0132\032.google.protobuf.TimestampB\003" + + "\340A\003H\001\210\001\001B\031\n\027_terminal_storage_classB%\n#_" + + "terminal_storage_class_update_time\032-\n\025Hi" + + "erarchicalNamespace\022\024\n\007enabled\030\001 \001(\010B\003\340A" + + "\001\032-\n\013LabelsEntry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002" + + " \001(\t:\0028\001:G\352AD\n\035storage.googleapis.com/Bu" + + "cket\022#projects/{project}/buckets/{bucket" + + "}\"\316\001\n\023BucketAccessControl\022\014\n\004role\030\001 \001(\t\022" + + "\n\n\002id\030\002 \001(\t\022\016\n\006entity\030\003 \001(\t\022\027\n\nentity_al" + + "t\030\t \001(\tB\003\340A\003\022\021\n\tentity_id\030\004 \001(\t\022\014\n\004etag\030" + + "\010 \001(\t\022\r\n\005email\030\005 \001(\t\022\016\n\006domain\030\006 \001(\t\0224\n\014" + + "project_team\030\007 \001(\0132\036.google.storage.v2.P" + + "rojectTeam\"I\n\017ChecksummedData\022\026\n\007content" + + "\030\001 \001(\014B\005\010\001\340A\001\022\023\n\006crc32c\030\002 \001(\007H\000\210\001\001B\t\n\007_c" + + "rc32c\"C\n\017ObjectChecksums\022\023\n\006crc32c\030\001 \001(\007" + + "H\000\210\001\001\022\020\n\010md5_hash\030\002 \001(\014B\t\n\007_crc32c\"\255\002\n\017H" + + "macKeyMetadata\022\017\n\002id\030\001 \001(\tB\003\340A\005\022\026\n\tacces" + + "s_id\030\002 \001(\tB\003\340A\005\022D\n\007project\030\003 \001(\tB3\340A\005\372A-", + "\n+cloudresourcemanager.googleapis.com/Pr" + + "oject\022\"\n\025service_account_email\030\004 \001(\tB\003\340A" + + "\003\022\r\n\005state\030\005 \001(\t\0224\n\013create_time\030\006 \001(\0132\032." + + "google.protobuf.TimestampB\003\340A\003\0224\n\013update" + + "_time\030\007 \001(\0132\032.google.protobuf.TimestampB" + + "\003\340A\003\022\014\n\004etag\030\010 \001(\t\"\247\003\n\022NotificationConfi" + + "g\022\021\n\004name\030\001 \001(\tB\003\340A\002\022\022\n\005topic\030\002 \001(\tB\003\340A\002" + + "\022\014\n\004etag\030\007 \001(\t\022\023\n\013event_types\030\003 \003(\t\022V\n\021c" + + "ustom_attributes\030\004 \003(\0132;.google.storage." + + "v2.NotificationConfig.CustomAttributesEn" + + "try\022\032\n\022object_name_prefix\030\005 \001(\t\022\033\n\016paylo" + + "ad_format\030\006 \001(\tB\003\340A\002\0327\n\025CustomAttributes" + + "Entry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001:}\352" + + "Az\n)storage.googleapis.com/NotificationC" + + "onfig\022Mprojects/{project}/buckets/{bucke" + + "t}/notificationConfigs/{notification_con" + + "fig}\"L\n\022CustomerEncryption\022\034\n\024encryption" + + "_algorithm\030\001 \001(\t\022\030\n\020key_sha256_bytes\030\003 \001" + + "(\014\"\254\n\n\006Object\022\021\n\004name\030\001 \001(\tB\003\340A\005\0225\n\006buck" + + "et\030\002 \001(\tB%\340A\005\372A\037\n\035storage.googleapis.com" + + "/Bucket\022\014\n\004etag\030\033 \001(\t\022\027\n\ngeneration\030\003 \001(" + + "\003B\003\340A\005\022\033\n\016metageneration\030\004 \001(\003B\003\340A\003\022\025\n\rs" + + "torage_class\030\005 \001(\t\022\021\n\004size\030\006 \001(\003B\003\340A\003\022\030\n" + + "\020content_encoding\030\007 \001(\t\022\033\n\023content_dispo" + + "sition\030\010 \001(\t\022\025\n\rcache_control\030\t \001(\t\0223\n\003a" + + "cl\030\n \003(\0132&.google.storage.v2.ObjectAcces" + + "sControl\022\030\n\020content_language\030\013 \001(\t\0224\n\013de" + + "lete_time\030\014 \001(\0132\032.google.protobuf.Timest" + + "ampB\003\340A\003\022\024\n\014content_type\030\r \001(\t\0224\n\013create" + + "_time\030\016 \001(\0132\032.google.protobuf.TimestampB" + + "\003\340A\003\022\034\n\017component_count\030\017 \001(\005B\003\340A\003\022:\n\tch" + + "ecksums\030\020 \001(\0132\".google.storage.v2.Object" + + "ChecksumsB\003\340A\003\0224\n\013update_time\030\021 \001(\0132\032.go" + + "ogle.protobuf.TimestampB\003\340A\003\0227\n\007kms_key\030" + + "\022 \001(\tB&\372A#\n!cloudkms.googleapis.com/Cryp" + + "toKey\022B\n\031update_storage_class_time\030\023 \001(\013" + + "2\032.google.protobuf.TimestampB\003\340A\003\022\026\n\016tem" + + "porary_hold\030\024 \001(\010\0229\n\025retention_expire_ti" + + "me\030\025 \001(\0132\032.google.protobuf.Timestamp\0229\n\010" + + "metadata\030\026 \003(\0132\'.google.storage.v2.Objec" + + "t.MetadataEntry\022\035\n\020event_based_hold\030\027 \001(" + + "\010H\000\210\001\001\022,\n\005owner\030\030 \001(\0132\030.google.storage.v" + + "2.OwnerB\003\340A\003\022B\n\023customer_encryption\030\031 \001(" + + "\0132%.google.storage.v2.CustomerEncryption" + + "\022/\n\013custom_time\030\032 \001(\0132\032.google.protobuf." + + "Timestamp\022>\n\020soft_delete_time\030\034 \001(\0132\032.go" + + "ogle.protobuf.TimestampB\003\340A\003H\001\210\001\001\022>\n\020har" + + "d_delete_time\030\035 \001(\0132\032.google.protobuf.Ti" + + "mestampB\003\340A\003H\002\210\001\001\032/\n\rMetadataEntry\022\013\n\003ke" + + "y\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001B\023\n\021_event_bas" + + "ed_holdB\023\n\021_soft_delete_timeB\023\n\021_hard_de" + + "lete_time\"\316\001\n\023ObjectAccessControl\022\014\n\004rol" + + "e\030\001 \001(\t\022\n\n\002id\030\002 \001(\t\022\016\n\006entity\030\003 \001(\t\022\027\n\ne" + + "ntity_alt\030\t \001(\tB\003\340A\003\022\021\n\tentity_id\030\004 \001(\t\022" + + "\014\n\004etag\030\010 \001(\t\022\r\n\005email\030\005 \001(\t\022\016\n\006domain\030\006" + + " \001(\t\0224\n\014project_team\030\007 \001(\0132\036.google.stor" + + "age.v2.ProjectTeam\"l\n\023ListObjectsRespons" + + "e\022*\n\007objects\030\001 \003(\0132\031.google.storage.v2.O" + + "bject\022\020\n\010prefixes\030\002 \003(\t\022\027\n\017next_page_tok" + + "en\030\003 \001(\t\"3\n\013ProjectTeam\022\026\n\016project_numbe" + + "r\030\001 \001(\t\022\014\n\004team\030\002 \001(\t\"\'\n\016ServiceAccount\022" + + "\025\n\remail_address\030\001 \001(\t\"*\n\005Owner\022\016\n\006entit" + + "y\030\001 \001(\t\022\021\n\tentity_id\030\002 \001(\t\"C\n\014ContentRan" + + "ge\022\r\n\005start\030\001 \001(\003\022\013\n\003end\030\002 \001(\003\022\027\n\017comple" + + "te_length\030\003 \001(\0032\252\'\n\007Storage\022r\n\014DeleteBuc" + + "ket\022&.google.storage.v2.DeleteBucketRequ" + + "est\032\026.google.protobuf.Empty\"\"\332A\004name\212\323\344\223" + + "\002\025\022\023\n\004name\022\013{bucket=**}\022o\n\tGetBucket\022#.g" + + "oogle.storage.v2.GetBucketRequest\032\031.goog" + + "le.storage.v2.Bucket\"\"\332A\004name\212\323\344\223\002\025\022\023\n\004n" + + "ame\022\013{bucket=**}\022\253\001\n\014CreateBucket\022&.goog" + + "le.storage.v2.CreateBucketRequest\032\031.goog" + + "le.storage.v2.Bucket\"X\332A\027parent,bucket,b" + + "ucket_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\013ListB" + + "uckets\022%.google.storage.v2.ListBucketsRe" + + "quest\032&.google.storage.v2.ListBucketsRes" + + "ponse\"\'\332A\006parent\212\323\344\223\002\030\022\026\n\006parent\022\014{proje" + + "ct=**}\022\223\001\n\031LockBucketRetentionPolicy\0223.g" + + "oogle.storage.v2.LockBucketRetentionPoli" + + "cyRequest\032\031.google.storage.v2.Bucket\"&\332A" + + "\006bucket\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}\022u\n\014" + + "GetIamPolicy\022\".google.iam.v1.GetIamPolic" + + "yRequest\032\025.google.iam.v1.Policy\"*\332A\010reso" + + "urce\212\323\344\223\002\031\022\027\n\010resource\022\013{bucket=**}\022|\n\014S" + + "etIamPolicy\022\".google.iam.v1.SetIamPolicy" + + "Request\032\025.google.iam.v1.Policy\"1\332A\017resou" + + "rce,policy\212\323\344\223\002\031\022\027\n\010resource\022\013{bucket=**" + + "}\022\327\001\n\022TestIamPermissions\022(.google.iam.v1" + + ".TestIamPermissionsRequest\032).google.iam." + + "v1.TestIamPermissionsResponse\"l\332A\024resour" + + "ce,permissions\212\323\344\223\002O\022\027\n\010resource\022\013{bucke" + + "t=**}\0224\n\010resource\022({bucket=projects/*/bu" + + "ckets/*}/objects/**\022\212\001\n\014UpdateBucket\022&.g" + + "oogle.storage.v2.UpdateBucketRequest\032\031.g" + + "oogle.storage.v2.Bucket\"7\332A\022bucket,updat" + + "e_mask\212\323\344\223\002\034\022\032\n\013bucket.name\022\013{bucket=**}" + + "\022\237\001\n\030DeleteNotificationConfig\0222.google.s" + + "torage.v2.DeleteNotificationConfigReques" + + "t\032\026.google.protobuf.Empty\"7\332A\004name\212\323\344\223\002*" + + "\022(\n\004name\022 {bucket=projects/*/buckets/*}/" + + "**\022\250\001\n\025GetNotificationConfig\022/.google.st" + + "orage.v2.GetNotificationConfigRequest\032%." + + "google.storage.v2.NotificationConfig\"7\332A" + + "\004name\212\323\344\223\002*\022(\n\004name\022 {bucket=projects/*/" + + "buckets/*}/**\022\261\001\n\030CreateNotificationConf" + + "ig\0222.google.storage.v2.CreateNotificatio" + + "nConfigRequest\032%.google.storage.v2.Notif" + + "icationConfig\":\332A\032parent,notification_co" + + "nfig\212\323\344\223\002\027\022\025\n\006parent\022\013{bucket=**}\022\250\001\n\027Li" + + "stNotificationConfigs\0221.google.storage.v" + + "2.ListNotificationConfigsRequest\0322.googl" + + "e.storage.v2.ListNotificationConfigsResp" + + "onse\"&\332A\006parent\212\323\344\223\002\027\022\025\n\006parent\022\013{bucket" + + "=**}\022~\n\rComposeObject\022\'.google.storage.v" + + "2.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.s" + + "torage.v2.DeleteObjectRequest\032\026.google.p" + + "rotobuf.Empty\"H\332A\rbucket,object\332A\030bucket" + + ",object,generation\212\323\344\223\002\027\022\025\n\006bucket\022\013{buc" + + "ket=**}\022\215\001\n\rRestoreObject\022\'.google.stora" + + "ge.v2.RestoreObjectRequest\032\031.google.stor" + + "age.v2.Object\"8\332A\030bucket,object,generati" + + "on\212\323\344\223\002\027\022\025\n\006bucket\022\013{bucket=**}\022\272\001\n\024Canc" + + "elResumableWrite\022..google.storage.v2.Can" + + "celResumableWriteRequest\032/.google.storag" + + "e.v2.CancelResumableWriteResponse\"A\332A\tup" + + "load_id\212\323\344\223\002/\022-\n\tupload_id\022 {bucket=proj" + + "ects/*/buckets/*}/**\022\225\001\n\tGetObject\022#.goo" + + "gle.storage.v2.GetObjectRequest\032\031.google" + + ".storage.v2.Object\"H\332A\rbucket,object\332A\030b" + + "ucket,object,generation\212\323\344\223\002\027\022\025\n\006bucket\022" + + "\013{bucket=**}\022\245\001\n\nReadObject\022$.google.sto" + + "rage.v2.ReadObjectRequest\032%.google.stora" + + "ge.v2.ReadObjectResponse\"H\332A\rbucket,obje" + + "ct\332A\030bucket,object,generation\212\323\344\223\002\027\022\025\n\006b" + + "ucket\022\013{bucket=**}0\001\022\214\001\n\014UpdateObject\022&." + + "google.storage.v2.UpdateObjectRequest\032\031." + + "google.storage.v2.Object\"9\332A\022object,upda" + + "te_mask\212\323\344\223\002\036\022\034\n\robject.bucket\022\013{bucket=" + + "**}\022`\n\013WriteObject\022%.google.storage.v2.W" + + "riteObjectRequest\032&.google.storage.v2.Wr" + + "iteObjectResponse\"\000(\001\022n\n\017BidiWriteObject" + + "\022).google.storage.v2.BidiWriteObjectRequ" + + "est\032*.google.storage.v2.BidiWriteObjectR" + + "esponse\"\000(\0010\001\022\204\001\n\013ListObjects\022%.google.s" + + "torage.v2.ListObjectsRequest\032&.google.st" + + "orage.v2.ListObjectsResponse\"&\332A\006parent\212" + + "\323\344\223\002\027\022\025\n\006parent\022\013{bucket=**}\022\230\001\n\rRewrite" + + "Object\022\'.google.storage.v2.RewriteObject" + + "Request\032\".google.storage.v2.RewriteRespo" + + "nse\":\212\323\344\223\0024\022\017\n\rsource_bucket\022!\n\022destinat" + + "ion_bucket\022\013{bucket=**}\022\256\001\n\023StartResumab" + + "leWrite\022-.google.storage.v2.StartResumab" + + "leWriteRequest\032..google.storage.v2.Start" + + "ResumableWriteResponse\"8\212\323\344\223\0022\0220\n!write_" + + "object_spec.resource.bucket\022\013{bucket=**}" + + "\022\256\001\n\020QueryWriteStatus\022*.google.storage.v" + + "2.QueryWriteStatusRequest\032+.google.stora" + + "ge.v2.QueryWriteStatusResponse\"A\332A\tuploa" + + "d_id\212\323\344\223\002/\022-\n\tupload_id\022 {bucket=project" + + "s/*/buckets/*}/**\022\200\001\n\021GetServiceAccount\022" + + "+.google.storage.v2.GetServiceAccountReq" + + "uest\032!.google.storage.v2.ServiceAccount\"" + + "\033\332A\007project\212\323\344\223\002\013\022\t\n\007project\022\225\001\n\rCreateH" + + "macKey\022\'.google.storage.v2.CreateHmacKey" + + "Request\032(.google.storage.v2.CreateHmacKe" + + "yResponse\"1\332A\035project,service_account_em" + + "ail\212\323\344\223\002\013\022\t\n\007project\022w\n\rDeleteHmacKey\022\'." + + "google.storage.v2.DeleteHmacKeyRequest\032\026" + + ".google.protobuf.Empty\"%\332A\021access_id,pro" + + "ject\212\323\344\223\002\013\022\t\n\007project\022}\n\nGetHmacKey\022$.go" + + "ogle.storage.v2.GetHmacKeyRequest\032\".goog" + + "le.storage.v2.HmacKeyMetadata\"%\332A\021access" + + "_id,project\212\323\344\223\002\013\022\t\n\007project\022|\n\014ListHmac" + + "Keys\022&.google.storage.v2.ListHmacKeysReq" + + "uest\032\'.google.storage.v2.ListHmacKeysRes" + + "ponse\"\033\332A\007project\212\323\344\223\002\013\022\t\n\007project\022\235\001\n\rU" + + "pdateHmacKey\022\'.google.storage.v2.UpdateH" + + "macKeyRequest\032\".google.storage.v2.HmacKe" + + "yMetadata\"?\332A\024hmac_key,update_mask\212\323\344\223\002\"" + + "\022 \n\020hmac_key.project\022\014{project=**}\032\247\002\312A\026" + + "storage.googleapis.com\322A\212\002https://www.go" + + "ogleapis.com/auth/cloud-platform,https:/" + + "/www.googleapis.com/auth/cloud-platform." + + "read-only,https://www.googleapis.com/aut" + + "h/devstorage.full_control,https://www.go" + + "ogleapis.com/auth/devstorage.read_only,h" + + "ttps://www.googleapis.com/auth/devstorag" + + "e.read_writeB\342\001\n\025com.google.storage.v2B\014" + + "StorageProtoP\001Z>cloud.google.com/go/stor" + + "age/internal/apiv2/storagepb;storagepb\352A" + + "x\n!cloudkms.googleapis.com/CryptoKey\022Spr" + + "ojects/{project}/locations/{location}/ke" + + "yRings/{key_ring}/cryptoKeys/{crypto_key" + + "}b\006proto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom( @@ -1261,6 +1270,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "LexicographicStart", "LexicographicEnd", "SoftDeleted", + "IncludeFoldersAsPrefixes", "MatchGlob", }); internal_static_google_storage_v2_QueryWriteStatusRequest_descriptor = @@ -1459,6 +1469,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "SatisfiesPzs", "CustomPlacementConfig", "Autoclass", + "HierarchicalNamespace", "SoftDeletePolicy", }); internal_static_google_storage_v2_Bucket_Billing_descriptor = @@ -1599,8 +1610,16 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { new java.lang.String[] { "Enabled", "ToggleTime", "TerminalStorageClass", "TerminalStorageClassUpdateTime", }); - internal_static_google_storage_v2_Bucket_LabelsEntry_descriptor = + internal_static_google_storage_v2_Bucket_HierarchicalNamespace_descriptor = internal_static_google_storage_v2_Bucket_descriptor.getNestedTypes().get(12); + internal_static_google_storage_v2_Bucket_HierarchicalNamespace_fieldAccessorTable = + new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_google_storage_v2_Bucket_HierarchicalNamespace_descriptor, + new java.lang.String[] { + "Enabled", + }); + internal_static_google_storage_v2_Bucket_LabelsEntry_descriptor = + internal_static_google_storage_v2_Bucket_descriptor.getNestedTypes().get(13); internal_static_google_storage_v2_Bucket_LabelsEntry_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_google_storage_v2_Bucket_LabelsEntry_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 a8516a58e..62922eadf 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 @@ -1248,6 +1248,11 @@ message ListObjectsRequest { // Soft delete policy is required to set this option. bool soft_deleted = 12 [(google.api.field_behavior) = OPTIONAL]; + // Optional. If true, will also include folders and managed folders (besides + // objects) in the returned `prefixes`. Requires `delimiter` to be set to '/'. + bool include_folders_as_prefixes = 13 + [(google.api.field_behavior) = OPTIONAL]; + // Optional. Filter results to objects and prefixes that match this glob // pattern. See [List Objects Using // Glob](https://cloud.google.com/storage/docs/json_api/v1/objects/list#list-objects-and-prefixes-using-glob) @@ -1988,6 +1993,12 @@ message Bucket { [(google.api.field_behavior) = OUTPUT_ONLY]; } + // Configuration for a bucket's hierarchical namespace feature. + message HierarchicalNamespace { + // Optional. Enables the hierarchical namespace feature. + bool enabled = 1 [(google.api.field_behavior) = OPTIONAL]; + } + // Immutable. The name of the bucket. // Format: `projects/{project}/buckets/{bucket}` string name = 1 [(google.api.field_behavior) = IMMUTABLE]; @@ -2136,6 +2147,12 @@ message Bucket { // Autoclass feature will be disabled and have no effect on the bucket. Autoclass autoclass = 28; + // Optional. The bucket's hierarchical namespace configuration. If there is no + // configuration, the hierarchical namespace feature will be disabled and have + // no effect on the bucket. + HierarchicalNamespace hierarchical_namespace = 32 + [(google.api.field_behavior) = OPTIONAL]; + // Optional. The bucket's soft delete policy. The soft delete policy prevents // soft-deleted objects from being permanently deleted. SoftDeletePolicy soft_delete_policy = 31 From d99b978f1a84cecc94acf6ea992609bfb5d0e40a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 13 Mar 2024 18:32:22 +0100 Subject: [PATCH 07/14] test(deps): update cross product test dependencies (#2439) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test(deps): update cross product test dependencies * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- google-cloud-storage/pom.xml | 6 +++--- pom.xml | 2 +- samples/install-without-bom/pom.xml | 2 +- samples/native-image-sample/pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- samples/snippets/pom.xml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml index a7138c4b6..604b126fb 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -16,7 +16,7 @@ google-cloud-storage - 1.109.1 + 1.109.2 5.10.2 @@ -173,13 +173,13 @@ com.google.api.grpc proto-google-cloud-kms-v1 - 0.130.0 + 0.131.0 test com.google.cloud google-cloud-kms - 2.39.0 + 2.40.0 test diff --git a/pom.xml b/pom.xml index 6a1297cac..98845612a 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ com.google.cloud google-cloud-pubsub - 1.127.1 + 1.127.2 test diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 4603242fa..2f8aca59a 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-pubsub - 1.127.1 + 1.127.2 test diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml index db9dad2f3..2f4f14a4b 100644 --- a/samples/native-image-sample/pom.xml +++ b/samples/native-image-sample/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-pubsub - 1.127.1 + 1.127.2 test diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index d875f8e60..6211bd424 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -52,7 +52,7 @@ com.google.cloud google-cloud-pubsub - 1.127.1 + 1.127.2 test diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index da562bc01..b9c0b93c9 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -72,7 +72,7 @@ com.google.cloud google-cloud-pubsub - 1.127.1 + 1.127.2 test From 736865b4b97aa3940e1eab6a582d0ef38db31bba Mon Sep 17 00:00:00 2001 From: Al Arafat Tanin <140037180+rng70-or@users.noreply.github.com> Date: Thu, 14 Mar 2024 00:06:17 +0600 Subject: [PATCH 08/14] fix: missing serialVersionUID of serializable classes (#2344) * fix: add missing serial_version_uid to serializable classes * chore: make HttpStorageOptions.RetryDependenciesAdapter transient * chore: fmt --------- Co-authored-by: BenWhitehead --- .../com/google/cloud/storage/GrpcStorageOptions.java | 1 + .../com/google/cloud/storage/HttpStorageOptions.java | 12 +++++++++--- .../java/com/google/cloud/storage/Notification.java | 1 + .../com/google/cloud/storage/StorageOptions.java | 3 +++ .../java/com/google/cloud/storage/UnifiedOpts.java | 3 +++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageOptions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageOptions.java index dcadfb401..841343d31 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageOptions.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcStorageOptions.java @@ -767,6 +767,7 @@ protected StorageSettings.Builder setInternalHeaderProvider( private static final class NoopGrpcInterceptorProvider implements GrpcInterceptorProvider, Serializable { + private static long serialVersionUID = -8523033236999805349L; private static final NoopGrpcInterceptorProvider INSTANCE = new NoopGrpcInterceptorProvider(); @Override diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/HttpStorageOptions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/HttpStorageOptions.java index 9d4873e2b..fd2a57311 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/HttpStorageOptions.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/HttpStorageOptions.java @@ -36,6 +36,8 @@ import com.google.cloud.storage.spi.v1.StorageRpc; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableSet; +import java.io.IOException; +import java.io.ObjectInputStream; import java.io.Serializable; import java.util.Set; @@ -52,7 +54,7 @@ public class HttpStorageOptions extends StorageOptions { private static final String DEFAULT_HOST = "https://storage.googleapis.com"; private final HttpRetryAlgorithmManager retryAlgorithmManager; - private final RetryDependenciesAdapter retryDepsAdapter; + private transient RetryDependenciesAdapter retryDepsAdapter; private HttpStorageOptions(Builder builder, StorageDefaults serviceDefaults) { super(builder, serviceDefaults); @@ -93,6 +95,11 @@ public boolean equals(Object obj) { return obj instanceof HttpStorageOptions && baseEquals((HttpStorageOptions) obj); } + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + this.retryDepsAdapter = new RetryDependenciesAdapter(); + } + public static HttpStorageOptions.Builder newBuilder() { return new HttpStorageOptions.Builder().setHost(DEFAULT_HOST); } @@ -345,8 +352,7 @@ public ServiceRpc create(StorageOptions options) { * We don't yet want to make HttpStorageOptions itself implement {@link RetryingDependencies} but * we do need use it in a couple places, for those we create this adapter. */ - private final class RetryDependenciesAdapter implements RetryingDependencies, Serializable { - + private final class RetryDependenciesAdapter implements RetryingDependencies { private RetryDependenciesAdapter() {} @Override diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java index f3e2bb81a..f3e0738d5 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -26,6 +26,7 @@ * details. */ public class Notification extends NotificationInfo { + private static final long serialVersionUID = 3150928330690874200L; private final StorageOptions options; private transient Storage storage; diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageOptions.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageOptions.java index 74a6ffb3d..53ad6142e 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageOptions.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageOptions.java @@ -63,6 +63,8 @@ public abstract class StorageOptions extends ServiceOptions Date: Thu, 14 Mar 2024 10:37:47 -0700 Subject: [PATCH 09/14] feat: add hierarchical namespace and folders features (#2445) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: support includeFolders list option * Add grpc and HNS * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix tests * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix tests again * fix clirr --------- Co-authored-by: Owl Bot --- .../clirr-ignored-differences.xml | 6 ++ .../java/com/google/cloud/storage/Bucket.java | 6 ++ .../com/google/cloud/storage/BucketInfo.java | 87 +++++++++++++++++++ .../google/cloud/storage/GrpcConversions.java | 26 ++++++ .../google/cloud/storage/JsonConversions.java | 26 ++++++ .../com/google/cloud/storage/Storage.java | 11 +++ .../com/google/cloud/storage/UnifiedOpts.java | 18 ++++ .../cloud/storage/spi/v1/HttpStorageRpc.java | 1 + .../cloud/storage/spi/v1/StorageRpc.java | 4 +- .../storage/it/ITBucketReadMaskTest.java | 1 + .../google/cloud/storage/it/ITBucketTest.java | 76 ++++++++++++++++ .../storage/it/ITOptionRegressionTest.java | 2 + 12 files changed, 263 insertions(+), 1 deletion(-) diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml index ba3233873..635e882a6 100644 --- a/google-cloud-storage/clirr-ignored-differences.xml +++ b/google-cloud-storage/clirr-ignored-differences.xml @@ -15,6 +15,12 @@ * writeAndClose(*) + + 7013 + com/google/cloud/storage/BucketInfo$Builder + com.google.cloud.storage.BucketInfo$Builder setHierarchicalNamespace(com.google.cloud.storage.BucketInfo$HierarchicalNamespace) + + 7013 com/google/cloud/storage/BlobInfo$Builder 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 3c1652bc9..6459e0a0a 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 @@ -748,6 +748,12 @@ Builder setObjectRetention(ObjectRetention objectRetention) { return this; } + @Override + public Builder setHierarchicalNamespace(HierarchicalNamespace hierarchicalNamespace) { + infoBuilder.setHierarchicalNamespace(hierarchicalNamespace); + return this; + } + @Override public Bucket build() { return new Bucket(storage, 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 9fb46b5bd..af3e4436e 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 @@ -118,6 +118,7 @@ public class BucketInfo implements Serializable { private final Logging logging; private final CustomPlacementConfig customPlacementConfig; private final ObjectRetention objectRetention; + private final HierarchicalNamespace hierarchicalNamespace; private final transient ImmutableSet modifiedFields; @@ -713,6 +714,71 @@ public Logging build() { } } + /** The bucket's hierarchical namespace (Folders) configuration. Enable this to use HNS. */ + public static final class HierarchicalNamespace implements Serializable { + + private static final long serialVersionUID = 5932926691444613101L; + private Boolean enabled; + + public Boolean getEnabled() { + return enabled; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof HierarchicalNamespace)) { + return false; + } + HierarchicalNamespace that = (HierarchicalNamespace) o; + return Objects.equals(enabled, that.enabled); + } + + @Override + public int hashCode() { + return Objects.hash(enabled); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("enabled", enabled).toString(); + } + + private HierarchicalNamespace() {} + + private HierarchicalNamespace(Builder builder) { + this.enabled = builder.enabled; + } + + public static Builder newBuilder() { + return new Builder(); + } + + public Builder toBuilder() { + return newBuilder().setEnabled(enabled); + } + + public static final class Builder { + private Boolean enabled; + + /** + * Sets whether Hierarchical Namespace (Folders) is enabled for this bucket. This can only be + * enabled at bucket create time. If this is enabled, Uniform Bucket-Level Access must also be + * enabled. + */ + public Builder setEnabled(Boolean enabled) { + this.enabled = enabled; + return this; + } + + public HierarchicalNamespace build() { + return new HierarchicalNamespace(this); + } + } + } + /** * Lifecycle rule for a bucket. Allows supported Actions, such as deleting and changing storage * class, to be executed when certain Conditions are met. @@ -1683,6 +1749,8 @@ public Builder setRetentionPeriodDuration(Duration retentionPeriod) { public abstract Builder setCustomPlacementConfig(CustomPlacementConfig customPlacementConfig); + public abstract Builder setHierarchicalNamespace(HierarchicalNamespace hierarchicalNamespace); + abstract Builder setObjectRetention(ObjectRetention objectRetention); /** Creates a {@code BucketInfo} object. */ @@ -1783,6 +1851,7 @@ static final class BuilderImpl extends Builder { private Logging logging; private CustomPlacementConfig customPlacementConfig; private ObjectRetention objectRetention; + private HierarchicalNamespace hierarchicalNamespace; private final ImmutableSet.Builder modifiedFields = ImmutableSet.builder(); BuilderImpl(String name) { @@ -1822,6 +1891,7 @@ static final class BuilderImpl extends Builder { logging = bucketInfo.logging; customPlacementConfig = bucketInfo.customPlacementConfig; objectRetention = bucketInfo.objectRetention; + hierarchicalNamespace = bucketInfo.hierarchicalNamespace; } @Override @@ -2187,6 +2257,15 @@ Builder setObjectRetention(ObjectRetention objectRetention) { return this; } + @Override + public Builder setHierarchicalNamespace(HierarchicalNamespace hierarchicalNamespace) { + if (!Objects.equals(this.hierarchicalNamespace, hierarchicalNamespace)) { + modifiedFields.add(BucketField.HIERARCHICAL_NAMESPACE); + } + this.hierarchicalNamespace = hierarchicalNamespace; + return this; + } + @Override Builder setLocationType(String locationType) { if (!Objects.equals(this.locationType, locationType)) { @@ -2428,6 +2507,7 @@ private Builder clearDeleteLifecycleRules() { logging = builder.logging; customPlacementConfig = builder.customPlacementConfig; objectRetention = builder.objectRetention; + hierarchicalNamespace = builder.hierarchicalNamespace; modifiedFields = builder.modifiedFields.build(); } @@ -2768,6 +2848,11 @@ public ObjectRetention getObjectRetention() { return objectRetention; } + /** Returns the Hierarchical Namespace (Folders) Configuration */ + public HierarchicalNamespace getHierarchicalNamespace() { + return hierarchicalNamespace; + } + /** Returns a builder for the current bucket. */ public Builder toBuilder() { return new BuilderImpl(this); @@ -2805,6 +2890,7 @@ public int hashCode() { autoclass, locationType, objectRetention, + hierarchicalNamespace, logging); } @@ -2846,6 +2932,7 @@ public boolean equals(Object o) { && Objects.equals(autoclass, that.autoclass) && Objects.equals(locationType, that.locationType) && Objects.equals(objectRetention, that.objectRetention) + && Objects.equals(hierarchicalNamespace, that.hierarchicalNamespace) && Objects.equals(logging, that.logging); } 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 9ddf229c5..d1084bc41 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 @@ -110,6 +110,10 @@ final class GrpcConversions { private final Codec iamConditionCodec = Codec.of(this::conditionEncode, this::conditionDecode); + private final Codec + hierarchicalNamespaceCodec = + Codec.of(this::hierarchicalNamespaceEncode, this::hierarchicalNamespaceDecode); + @VisibleForTesting final Codec timestampCodec = Codec.of( @@ -297,6 +301,10 @@ private BucketInfo bucketInfoDecode(Bucket from) { .setDataLocations(customPlacementConfig.getDataLocationsList()) .build()); } + if (from.hasHierarchicalNamespace()) { + to.setHierarchicalNamespace( + hierarchicalNamespaceCodec.decode(from.getHierarchicalNamespace())); + } // TODO(frankyn): Add SelfLink when the field is available if (!from.getEtag().isEmpty()) { to.setEtag(from.getEtag()); @@ -382,6 +390,10 @@ private Bucket bucketInfoEncode(BucketInfo from) { .addAllDataLocations(customPlacementConfig.getDataLocations()) .build()); } + ifNonNull( + from.getHierarchicalNamespace(), + hierarchicalNamespaceCodec::encode, + to::setHierarchicalNamespace); // TODO(frankyn): Add SelfLink when the field is available ifNonNull(from.getEtag(), to::setEtag); return to.build(); @@ -589,6 +601,20 @@ private Bucket.Autoclass autoclassEncode(BucketInfo.Autoclass from) { return to.build(); } + private Bucket.HierarchicalNamespace hierarchicalNamespaceEncode( + BucketInfo.HierarchicalNamespace from) { + Bucket.HierarchicalNamespace.Builder to = Bucket.HierarchicalNamespace.newBuilder(); + ifNonNull(from.getEnabled(), to::setEnabled); + return to.build(); + } + + private BucketInfo.HierarchicalNamespace hierarchicalNamespaceDecode( + Bucket.HierarchicalNamespace from) { + BucketInfo.HierarchicalNamespace.Builder to = BucketInfo.HierarchicalNamespace.newBuilder(); + to.setEnabled(from.getEnabled()); + return to.build(); + } + private Bucket.IamConfig iamConfigEncode(BucketInfo.IamConfiguration from) { Bucket.IamConfig.Builder to = Bucket.IamConfig.newBuilder(); to.setUniformBucketLevelAccess(ublaEncode(from)); 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 4bbf08d4b..c5add241d 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 @@ -137,6 +137,10 @@ final class JsonConversions { private final Codec blobInfoCodec = Codec.of(this::blobInfoEncode, this::blobInfoDecode); + private final Codec + hierarchicalNamespaceCodec = + Codec.of(this::hierarchicalNamespaceEncode, this::hierarchicalNamespaceDecode); + private final Codec notificationInfoCodec = Codec.of(this::notificationEncode, this::notificationDecode); private final Codec @@ -437,6 +441,10 @@ private Bucket bucketInfoEncode(BucketInfo from) { this::customPlacementConfigEncode, to::setCustomPlacementConfig); ifNonNull(from.getObjectRetention(), this::objectRetentionEncode, to::setObjectRetention); + ifNonNull( + from.getHierarchicalNamespace(), + this::hierarchicalNamespaceEncode, + to::setHierarchicalNamespace); return to; } @@ -487,6 +495,10 @@ private BucketInfo bucketInfoDecode(com.google.api.services.storage.model.Bucket from.getCustomPlacementConfig(), this::customPlacementConfigDecode, to::setCustomPlacementConfig); + ifNonNull( + from.getHierarchicalNamespace(), + this::hierarchicalNamespaceDecode, + to::setHierarchicalNamespace); ifNonNull(from.getObjectRetention(), this::objectRetentionDecode, to::setObjectRetention); return to.build(); } @@ -861,6 +873,20 @@ private com.google.api.services.storage.model.Notification notificationEncode( return to; } + private Bucket.HierarchicalNamespace hierarchicalNamespaceEncode( + BucketInfo.HierarchicalNamespace from) { + Bucket.HierarchicalNamespace to = new Bucket.HierarchicalNamespace(); + ifNonNull(from.getEnabled(), to::setEnabled); + return to; + } + + private BucketInfo.HierarchicalNamespace hierarchicalNamespaceDecode( + Bucket.HierarchicalNamespace from) { + BucketInfo.HierarchicalNamespace.Builder to = BucketInfo.HierarchicalNamespace.newBuilder(); + to.setEnabled(from.getEnabled()); + return to.build(); + } + private NotificationInfo notificationDecode( com.google.api.services.storage.model.Notification from) { NotificationInfo.Builder builder = new NotificationInfo.BuilderImpl(from.getTopic()); 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 5ca31c042..1d0ae8347 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 @@ -159,6 +159,9 @@ enum BucketField implements FieldSelector, NamedField { CUSTOM_PLACEMENT_CONFIG("customPlacementConfig", "custom_placement_config"), @TransportCompatibility({Transport.HTTP, Transport.GRPC}) AUTOCLASS("autoclass"), + + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + HIERARCHICAL_NAMESPACE("hierarchicalNamespace", "hierarchical_namespace"), @TransportCompatibility({Transport.HTTP}) OBJECT_RETENTION("objectRetention"); @@ -1788,6 +1791,14 @@ public static BlobListOption matchGlob(@NonNull String glob) { return new BlobListOption(UnifiedOpts.matchGlob(glob)); } + /** + * Returns an option for whether to include all Folders (including empty Folders) in response. + */ + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + public static BlobListOption includeFolders(boolean includeFolders) { + return new BlobListOption(UnifiedOpts.includeFoldersAsPrefixes(includeFolders)); + } + /** * Returns an option to define the billing user project. This option is required by buckets with * `requester_pays` flag enabled to assign operation costs. 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 dbf104e90..3159cbebb 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 @@ -370,6 +370,10 @@ static Delimiter delimiter(@NonNull String delimiter) { return new Delimiter(delimiter); } + static IncludeFoldersAsPrefixes includeFoldersAsPrefixes(boolean includeFoldersAsPrefixes) { + return new IncludeFoldersAsPrefixes(includeFoldersAsPrefixes); + } + @Deprecated static DetectContentType detectContentType() { return DetectContentType.INSTANCE; @@ -636,6 +640,20 @@ public Mapper rewriteObject() { } } + static final class IncludeFoldersAsPrefixes extends RpcOptVal implements ObjectListOpt { + + private static final long serialVersionUID = 321916692864878282L; + + private IncludeFoldersAsPrefixes(boolean val) { + super(StorageRpc.Option.INCLUDE_FOLDERS_AS_PREFIXES, val); + } + + @Override + public Mapper listObjects() { + return b -> b.setIncludeFoldersAsPrefixes(val); + } + } + static final class Delimiter extends RpcOptVal implements ObjectListOpt { private static final long serialVersionUID = -3789556789947615714L; diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java index 2f1c3e210..3ca2eabec 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java @@ -459,6 +459,7 @@ public Tuple> list(final String bucket, Map storageObjects = Iterables.concat( diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java index 7d671deed..3b40f6a23 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java @@ -73,7 +73,9 @@ enum Option { DETECT_CONTENT_TYPE("detectContentType"), ENABLE_OBJECT_RETENTION("enableObjectRetention"), RETURN_RAW_INPUT_STREAM("returnRawInputStream"), - OVERRIDE_UNLOCKED_RETENTION("overrideUnlockedRetention"); + OVERRIDE_UNLOCKED_RETENTION("overrideUnlockedRetention"), + INCLUDE_FOLDERS_AS_PREFIXES("includeFoldersAsPrefixes"); + ; private final String value; 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 93099d41e..9c9776032 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 @@ -133,6 +133,7 @@ public ImmutableList parameters() { new Args<>(BucketField.TIME_CREATED, LazyAssertion.equal()), new Args<>(BucketField.UPDATED, LazyAssertion.equal()), new Args<>(BucketField.VERSIONING, LazyAssertion.equal()), + new Args<>(BucketField.HIERARCHICAL_NAMESPACE, LazyAssertion.equal()), new Args<>(BucketField.WEBSITE, LazyAssertion.equal())); List argsDefined = diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java index e32be5c32..5b759be6b 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertTrue; import com.google.api.gax.paging.Page; +import com.google.api.services.storage.model.Folder; import com.google.cloud.Policy; import com.google.cloud.storage.Blob; import com.google.cloud.storage.BlobInfo; @@ -44,6 +45,7 @@ import com.google.cloud.storage.Storage.BucketListOption; import com.google.cloud.storage.Storage.BucketTargetOption; import com.google.cloud.storage.StorageClass; +import com.google.cloud.storage.StorageOptions; import com.google.cloud.storage.TestUtils; import com.google.cloud.storage.TransportCompatibility.Transport; import com.google.cloud.storage.it.runner.StorageITRunner; @@ -53,6 +55,7 @@ import com.google.cloud.storage.it.runner.annotations.CrossRun; import com.google.cloud.storage.it.runner.annotations.Inject; import com.google.cloud.storage.it.runner.registry.Generator; +import com.google.cloud.storage.spi.v1.HttpStorageRpc; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.time.Duration; @@ -551,6 +554,79 @@ public void testUpdateBucket_noModification() throws Exception { } } + @Test + public void createBucketWithHierarchicalNamespace() { + String bucketName = generator.randomBucketName(); + storage.create( + BucketInfo.newBuilder(bucketName) + .setHierarchicalNamespace( + BucketInfo.HierarchicalNamespace.newBuilder().setEnabled(true).build()) + .setIamConfiguration( + BucketInfo.IamConfiguration.newBuilder() + .setIsUniformBucketLevelAccessEnabled(true) + .build()) + .build()); + try { + Bucket remoteBucket = storage.get(bucketName); + assertNotNull(remoteBucket.getHierarchicalNamespace()); + assertTrue(remoteBucket.getHierarchicalNamespace().getEnabled()); + } finally { + BucketCleaner.doCleanup(bucketName, storage); + } + } + + @Test + public void testListObjectsWithFolders() throws Exception { + String bucketName = generator.randomBucketName(); + storage.create( + BucketInfo.newBuilder(bucketName) + .setHierarchicalNamespace( + BucketInfo.HierarchicalNamespace.newBuilder().setEnabled(true).build()) + .setIamConfiguration( + BucketInfo.IamConfiguration.newBuilder() + .setIsUniformBucketLevelAccessEnabled(true) + .build()) + .build()); + try { + com.google.api.services.storage.Storage apiaryStorage = + new HttpStorageRpc(StorageOptions.getDefaultInstance()).getStorage(); + apiaryStorage + .folders() + .insert(bucketName, new Folder().setName("F").setBucket(bucketName)) + .execute(); + + Page blobs = + storage.list( + bucketName, + Storage.BlobListOption.delimiter("/"), + Storage.BlobListOption.includeFolders(false)); + + boolean found = false; + for (Blob blob : blobs.iterateAll()) { + if (blob.getName().equals("F/")) { + found = true; + } + } + assert (!found); + + blobs = + storage.list( + bucketName, + Storage.BlobListOption.delimiter("/"), + Storage.BlobListOption.includeFolders(true)); + + for (Blob blob : blobs.iterateAll()) { + if (blob.getName().equals("F/")) { + found = true; + } + } + assert (found); + + } finally { + BucketCleaner.doCleanup(bucketName, storage); + } + } + private void unsetRequesterPays() { Bucket remoteBucket = storage.get( 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 4dbe55adc..7627bf3af 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 @@ -326,6 +326,7 @@ public void storage_BucketGetOption_fields_BucketField() { "timeCreated", "updated", "versioning", + "hierarchicalNamespace", "website"); s.get( b.getName(), @@ -816,6 +817,7 @@ public void storage_BucketListOption_fields_BucketField() { "items/timeCreated", "items/updated", "items/versioning", + "items/hierarchicalNamespace", "items/website"); s.list(BucketListOption.fields(TestUtils.filterOutHttpOnlyBucketFields(BucketField.values()))); requestAuditing.assertQueryParam("fields", expected, splitOnCommaToSet()); From 989f36fbb206832a6a3584c77546d3d560ac0df8 Mon Sep 17 00:00:00 2001 From: JesseLovelace <43148100+JesseLovelace@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:40:32 -0700 Subject: [PATCH 10/14] feat: add soft delete feature (#2403) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add soft delete feature * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * add softDeleteTime and hardDeleteTime object fields * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * add new fields to field tests * clirr ignore * remove debug comments * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * add softdeletetime and harddeletetime to grpc codec * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix read mask test * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix style issues * updates to apiary library * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix read mask test * fix typo --------- Co-authored-by: Owl Bot --- .../clirr-ignored-differences.xml | 18 +++ .../java/com/google/cloud/storage/Blob.java | 12 ++ .../com/google/cloud/storage/BlobInfo.java | 50 +++++++- .../java/com/google/cloud/storage/Bucket.java | 28 +++++ .../com/google/cloud/storage/BucketInfo.java | 108 ++++++++++++++++++ .../google/cloud/storage/GrpcConversions.java | 33 ++++++ .../storage/GrpcRetryAlgorithmManager.java | 5 + .../google/cloud/storage/GrpcStorageImpl.java | 28 +++++ .../storage/HttpRetryAlgorithmManager.java | 5 + .../google/cloud/storage/JsonConversions.java | 31 +++++ .../com/google/cloud/storage/Storage.java | 101 +++++++++++++++- .../com/google/cloud/storage/StorageImpl.java | 18 +++ .../com/google/cloud/storage/UnifiedOpts.java | 71 ++++++++++++ .../cloud/storage/spi/v1/HttpStorageRpc.java | 34 +++++- .../storage/spi/v1/HttpStorageRpcSpans.java | 1 + .../cloud/storage/spi/v1/StorageRpc.java | 11 +- .../storage/testing/StorageRpcTestBase.java | 5 + .../cloud/storage/it/ITBlobReadMaskTest.java | 4 +- .../storage/it/ITBucketReadMaskTest.java | 24 +++- .../google/cloud/storage/it/ITBucketTest.java | 61 ++++++++++ .../storage/it/ITOptionRegressionTest.java | 12 +- .../runner/registry/AbstractStorageProxy.java | 5 + 22 files changed, 654 insertions(+), 11 deletions(-) diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml index 635e882a6..7fffdb6bd 100644 --- a/google-cloud-storage/clirr-ignored-differences.xml +++ b/google-cloud-storage/clirr-ignored-differences.xml @@ -27,6 +27,24 @@ com.google.cloud.storage.BlobInfo$Builder setRetention(com.google.cloud.storage.BlobInfo$Retention) + + 7013 + com/google/cloud/storage/BucketInfo$Builder + com.google.cloud.storage.BucketInfo$Builder setSoftDeletePolicy(com.google.cloud.storage.BucketInfo$SoftDeletePolicy) + + + + 7012 + com/google/cloud/storage/Storage + com.google.cloud.storage.Blob restore(com.google.cloud.storage.BlobId, com.google.cloud.storage.Storage$BlobRestoreOption[]) + + + + 7012 + com/google/cloud/storage/spi/v1/StorageRpc + com.google.api.services.storage.model.StorageObject restore(com.google.api.services.storage.model.StorageObject, java.util.Map) + + 7009 diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java index e6295b8c6..c6ea7a2ce 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java @@ -526,6 +526,18 @@ Builder setRetentionExpirationTimeOffsetDateTime(OffsetDateTime retentionExpirat return this; } + @Override + Builder setSoftDeleteTime(OffsetDateTime softDeleteTime) { + infoBuilder.setSoftDeleteTime(softDeleteTime); + return this; + } + + @Override + Builder setHardDeleteTime(OffsetDateTime hardDeleteTime) { + infoBuilder.setHardDeleteTime(hardDeleteTime); + return this; + } + @Override public Builder setRetention(Retention retention) { infoBuilder.setRetention(retention); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java index e808f444c..52ce09fd7 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java @@ -108,6 +108,8 @@ public class BlobInfo implements Serializable { private final Boolean temporaryHold; private final OffsetDateTime retentionExpirationTime; private final Retention retention; + private final OffsetDateTime softDeleteTime; + private final OffsetDateTime hardDeleteTime; private final transient ImmutableSet modifiedFields; /** This class is meant for internal use only. Users are discouraged from using this class. */ @@ -525,6 +527,10 @@ Builder setRetentionExpirationTimeOffsetDateTime(OffsetDateTime retentionExpirat return setRetentionExpirationTime(millisOffsetDateTimeCodec.decode(retentionExpirationTime)); } + abstract Builder setSoftDeleteTime(OffsetDateTime offsetDateTime); + + abstract Builder setHardDeleteTime(OffsetDateTime hardDeleteTIme); + public abstract Builder setRetention(Retention retention); /** Creates a {@code BlobInfo} object. */ @@ -626,6 +632,8 @@ static final class BuilderImpl extends Builder { private Boolean temporaryHold; private OffsetDateTime retentionExpirationTime; private Retention retention; + private OffsetDateTime softDeleteTime; + private OffsetDateTime hardDeleteTime; private final ImmutableSet.Builder modifiedFields = ImmutableSet.builder(); BuilderImpl(BlobId blobId) { @@ -664,6 +672,8 @@ static final class BuilderImpl extends Builder { temporaryHold = blobInfo.temporaryHold; retentionExpirationTime = blobInfo.retentionExpirationTime; retention = blobInfo.retention; + softDeleteTime = blobInfo.softDeleteTime; + hardDeleteTime = blobInfo.hardDeleteTime; } @Override @@ -1037,6 +1047,24 @@ Builder setRetentionExpirationTimeOffsetDateTime(OffsetDateTime retentionExpirat return this; } + @Override + Builder setSoftDeleteTime(OffsetDateTime softDeleteTime) { + if (!Objects.equals(this.softDeleteTime, softDeleteTime)) { + modifiedFields.add(BlobField.SOFT_DELETE_TIME); + } + this.softDeleteTime = softDeleteTime; + return this; + } + + @Override + Builder setHardDeleteTime(OffsetDateTime hardDeleteTime) { + if (!Objects.equals(this.hardDeleteTime, hardDeleteTime)) { + modifiedFields.add(BlobField.HARD_DELETE_TIME); + } + this.hardDeleteTime = hardDeleteTime; + return this; + } + @Override public Builder setRetention(Retention retention) { // todo: b/308194853 @@ -1269,6 +1297,8 @@ Builder clearRetentionExpirationTime() { temporaryHold = builder.temporaryHold; retentionExpirationTime = builder.retentionExpirationTime; retention = builder.retention; + softDeleteTime = builder.softDeleteTime; + hardDeleteTime = builder.hardDeleteTime; modifiedFields = builder.modifiedFields.build(); } @@ -1662,6 +1692,18 @@ public OffsetDateTime getRetentionExpirationTimeOffsetDateTime() { return retentionExpirationTime; } + /** If this object has been soft-deleted, returns the time it was soft-deleted. */ + public OffsetDateTime getSoftDeleteTime() { + return softDeleteTime; + } + + /** + * If this object has been soft-deleted, returns the time at which it will be permanently deleted. + */ + public OffsetDateTime getHardDeleteTime() { + return hardDeleteTime; + } + /** Returns the object's Retention policy. */ public Retention getRetention() { return retention; @@ -1717,7 +1759,9 @@ public int hashCode() { eventBasedHold, temporaryHold, retention, - retentionExpirationTime); + retentionExpirationTime, + softDeleteTime, + hardDeleteTime); } @Override @@ -1759,7 +1803,9 @@ public boolean equals(Object o) { && Objects.equals(eventBasedHold, blobInfo.eventBasedHold) && Objects.equals(temporaryHold, blobInfo.temporaryHold) && Objects.equals(retentionExpirationTime, blobInfo.retentionExpirationTime) - && Objects.equals(retention, blobInfo.retention); + && Objects.equals(retention, blobInfo.retention) + && Objects.equals(softDeleteTime, blobInfo.softDeleteTime) + && Objects.equals(hardDeleteTime, blobInfo.hardDeleteTime); } ImmutableSet getModifiedFields() { 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 6459e0a0a..0587bb0b2 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 @@ -748,6 +748,12 @@ Builder setObjectRetention(ObjectRetention objectRetention) { return this; } + @Override + public Builder setSoftDeletePolicy(SoftDeletePolicy softDeletePolicy) { + infoBuilder.setSoftDeletePolicy(softDeletePolicy); + return this; + } + @Override public Builder setHierarchicalNamespace(HierarchicalNamespace hierarchicalNamespace) { infoBuilder.setHierarchicalNamespace(hierarchicalNamespace); @@ -1089,6 +1095,28 @@ public Blob get(String blob, BlobGetOption... options) { return storage.get(BlobId.of(getName(), blob), options); } + /** + * Returns the requested blob in this bucket of a specific generation or {@code null} if not + * found. + * + *

Example of getting a blob of a specific in the bucket. + * + *

{@code
+   * String blobName = "my_blob_name";
+   * long generation = 42;
+   * Blob blob = bucket.get(blobName, generation);
+   * }
+ * + * @param blob name of the requested blob + * @param generation the generation to get + * @param options blob search options + * @throws StorageException upon failure + */ + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + public Blob get(String blob, Long generation, BlobGetOption... options) { + return storage.get(BlobId.of(getName(), blob, generation), options); + } + /** * Returns a list of requested blobs in this bucket. Blobs that do not exist are null. * 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 af3e4436e..323555922 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 @@ -120,6 +120,8 @@ public class BucketInfo implements Serializable { private final ObjectRetention objectRetention; private final HierarchicalNamespace hierarchicalNamespace; + private final SoftDeletePolicy softDeletePolicy; + private final transient ImmutableSet modifiedFields; /** @@ -350,6 +352,90 @@ public String toString() { } } + /** + * The bucket's soft delete policy. If this policy is set, any deleted objects will be + * soft-deleted according to the time specified in the policy + */ + public static class SoftDeletePolicy implements Serializable { + + private static final long serialVersionUID = -8100190443052242908L; + private Duration retentionDuration; + private OffsetDateTime effectiveTime; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof SoftDeletePolicy)) { + return false; + } + SoftDeletePolicy that = (SoftDeletePolicy) o; + return Objects.equals(retentionDuration, that.retentionDuration) + && Objects.equals(effectiveTime, that.effectiveTime); + } + + @Override + public int hashCode() { + return Objects.hash(retentionDuration, effectiveTime); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("retentionDuration", retentionDuration) + .add("effectiveTime", effectiveTime) + .toString(); + } + + public static Builder newBuilder() { + return new Builder(); + } + + public Builder toBuilder() { + return new Builder().setRetentionDuration(retentionDuration).setEffectiveTime(effectiveTime); + } + + private SoftDeletePolicy() {} + + public SoftDeletePolicy(Builder builder) { + this.retentionDuration = builder.retentionDuration; + this.effectiveTime = builder.effectiveTime; + } + + public Duration getRetentionDuration() { + return retentionDuration; + } + + public OffsetDateTime getEffectiveTime() { + return effectiveTime; + } + + public static final class Builder { + private Duration retentionDuration; + private OffsetDateTime effectiveTime; + + /** Sets the length of time to retain soft-deleted objects for, expressed as a Duration */ + public Builder setRetentionDuration(Duration retentionDuration) { + this.retentionDuration = retentionDuration; + return this; + } + + /** + * Sets the time from which this soft-delete policy is effective. This is package-private + * because it can only be set by the backend. + */ + Builder setEffectiveTime(OffsetDateTime effectiveTime) { + this.effectiveTime = effectiveTime; + return this; + } + + public SoftDeletePolicy build() { + return new SoftDeletePolicy(this); + } + } + } + /** * Configuration for the Autoclass settings of a bucket. * @@ -1753,6 +1839,8 @@ public Builder setRetentionPeriodDuration(Duration retentionPeriod) { abstract Builder setObjectRetention(ObjectRetention objectRetention); + public abstract Builder setSoftDeletePolicy(SoftDeletePolicy softDeletePolicy); + /** Creates a {@code BucketInfo} object. */ public abstract BucketInfo build(); @@ -1851,6 +1939,8 @@ static final class BuilderImpl extends Builder { private Logging logging; private CustomPlacementConfig customPlacementConfig; private ObjectRetention objectRetention; + + private SoftDeletePolicy softDeletePolicy; private HierarchicalNamespace hierarchicalNamespace; private final ImmutableSet.Builder modifiedFields = ImmutableSet.builder(); @@ -1891,6 +1981,7 @@ static final class BuilderImpl extends Builder { logging = bucketInfo.logging; customPlacementConfig = bucketInfo.customPlacementConfig; objectRetention = bucketInfo.objectRetention; + softDeletePolicy = bucketInfo.softDeletePolicy; hierarchicalNamespace = bucketInfo.hierarchicalNamespace; } @@ -2257,6 +2348,15 @@ Builder setObjectRetention(ObjectRetention objectRetention) { return this; } + @Override + public Builder setSoftDeletePolicy(SoftDeletePolicy softDeletePolicy) { + if (!Objects.equals(this.softDeletePolicy, softDeletePolicy)) { + modifiedFields.add(BucketField.SOFT_DELETE_POLICY); + } + this.softDeletePolicy = softDeletePolicy; + return this; + } + @Override public Builder setHierarchicalNamespace(HierarchicalNamespace hierarchicalNamespace) { if (!Objects.equals(this.hierarchicalNamespace, hierarchicalNamespace)) { @@ -2507,6 +2607,7 @@ private Builder clearDeleteLifecycleRules() { logging = builder.logging; customPlacementConfig = builder.customPlacementConfig; objectRetention = builder.objectRetention; + softDeletePolicy = builder.softDeletePolicy; hierarchicalNamespace = builder.hierarchicalNamespace; modifiedFields = builder.modifiedFields.build(); } @@ -2848,6 +2949,11 @@ public ObjectRetention getObjectRetention() { return objectRetention; } + /** returns the Soft Delete policy */ + public SoftDeletePolicy getSoftDeletePolicy() { + return softDeletePolicy; + } + /** Returns the Hierarchical Namespace (Folders) Configuration */ public HierarchicalNamespace getHierarchicalNamespace() { return hierarchicalNamespace; @@ -2890,6 +2996,7 @@ public int hashCode() { autoclass, locationType, objectRetention, + softDeletePolicy, hierarchicalNamespace, logging); } @@ -2932,6 +3039,7 @@ public boolean equals(Object o) { && Objects.equals(autoclass, that.autoclass) && Objects.equals(locationType, that.locationType) && Objects.equals(objectRetention, that.objectRetention) + && Objects.equals(softDeletePolicy, that.softDeletePolicy) && Objects.equals(hierarchicalNamespace, that.hierarchicalNamespace) && Objects.equals(logging, that.logging); } 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 d1084bc41..28c51873b 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.SOFT_DELETE_POLICY; import static com.google.cloud.storage.Utils.bucketNameCodec; import static com.google.cloud.storage.Utils.ifNonNull; import static com.google.cloud.storage.Utils.lift; @@ -90,6 +91,9 @@ final class GrpcConversions { Codec.of(this::iamConfigEncode, this::iamConfigDecode); private final Codec autoclassCodec = Codec.of(this::autoclassEncode, this::autoclassDecode); + + private final Codec softDeletePolicyCodec = + Codec.of(this::softDeletePolicyEncode, this::softDeletePolicyDecode); private final Codec lifecycleRuleCodec = Codec.of(this::lifecycleRuleEncode, this::lifecycleRuleDecode); private final Codec bucketInfoCodec = @@ -294,6 +298,9 @@ private BucketInfo bucketInfoDecode(Bucket from) { if (from.hasAutoclass()) { to.setAutoclass(autoclassCodec.decode(from.getAutoclass())); } + if (from.hasSoftDeletePolicy()) { + to.setSoftDeletePolicy(softDeletePolicyCodec.decode(from.getSoftDeletePolicy())); + } if (from.hasCustomPlacementConfig()) { Bucket.CustomPlacementConfig customPlacementConfig = from.getCustomPlacementConfig(); to.setCustomPlacementConfig( @@ -383,6 +390,11 @@ private Bucket bucketInfoEncode(BucketInfo from) { ifNonNull(from.getAcl(), toImmutableListOf(bucketAclCodec::encode), to::addAllAcl); ifNonNull(from.getIamConfiguration(), iamConfigurationCodec::encode, to::setIamConfig); ifNonNull(from.getAutoclass(), autoclassCodec::encode, to::setAutoclass); + ifNonNull(from.getSoftDeletePolicy(), softDeletePolicyCodec::encode, to::setSoftDeletePolicy); + if (from.getModifiedFields().contains(SOFT_DELETE_POLICY) + && from.getSoftDeletePolicy() == null) { + to.clearSoftDeletePolicy(); + } CustomPlacementConfig customPlacementConfig = from.getCustomPlacementConfig(); if (customPlacementConfig != null && customPlacementConfig.getDataLocations() != null) { to.setCustomPlacementConfig( @@ -601,6 +613,19 @@ private Bucket.Autoclass autoclassEncode(BucketInfo.Autoclass from) { return to.build(); } + private BucketInfo.SoftDeletePolicy softDeletePolicyDecode(Bucket.SoftDeletePolicy from) { + BucketInfo.SoftDeletePolicy.Builder to = BucketInfo.SoftDeletePolicy.newBuilder(); + ifNonNull(from.getRetentionDuration(), durationCodec::decode, to::setRetentionDuration); + ifNonNull(from.getEffectiveTime(), timestampCodec::decode, to::setEffectiveTime); + return to.build(); + } + + private Bucket.SoftDeletePolicy softDeletePolicyEncode(BucketInfo.SoftDeletePolicy from) { + Bucket.SoftDeletePolicy.Builder to = Bucket.SoftDeletePolicy.newBuilder(); + ifNonNull(from.getRetentionDuration(), durationCodec::encode, to::setRetentionDuration); + return to.build(); + } + private Bucket.HierarchicalNamespace hierarchicalNamespaceEncode( BucketInfo.HierarchicalNamespace from) { Bucket.HierarchicalNamespace.Builder to = Bucket.HierarchicalNamespace.newBuilder(); @@ -863,6 +888,8 @@ private Object blobInfoEncode(BlobInfo from) { ifNonNull(from.getUpdateTimeOffsetDateTime(), timestampCodec::encode, toBuilder::setUpdateTime); ifNonNull(from.getCreateTimeOffsetDateTime(), timestampCodec::encode, toBuilder::setCreateTime); ifNonNull(from.getCustomTimeOffsetDateTime(), timestampCodec::encode, toBuilder::setCustomTime); + ifNonNull(from.getSoftDeleteTime(), timestampCodec::encode, toBuilder::setSoftDeleteTime); + ifNonNull(from.getHardDeleteTime(), timestampCodec::encode, toBuilder::setHardDeleteTime); ifNonNull( from.getCustomerEncryption(), customerEncryptionCodec::encode, @@ -928,6 +955,12 @@ private BlobInfo blobInfoDecode(Object from) { if (from.hasCustomerEncryption()) { toBuilder.setCustomerEncryption(customerEncryptionCodec.decode(from.getCustomerEncryption())); } + if (from.hasSoftDeleteTime()) { + toBuilder.setSoftDeleteTime(timestampCodec.decode(from.getSoftDeleteTime())); + } + if (from.hasHardDeleteTime()) { + toBuilder.setHardDeleteTime(timestampCodec.decode(from.getHardDeleteTime())); + } String storageClass = from.getStorageClass(); if (!storageClass.isEmpty()) { toBuilder.setStorageClass(StorageClass.valueOf(storageClass)); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcRetryAlgorithmManager.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcRetryAlgorithmManager.java index ea481ab25..de7af195b 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcRetryAlgorithmManager.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/GrpcRetryAlgorithmManager.java @@ -41,6 +41,7 @@ import com.google.storage.v2.LockBucketRetentionPolicyRequest; import com.google.storage.v2.QueryWriteStatusRequest; import com.google.storage.v2.ReadObjectRequest; +import com.google.storage.v2.RestoreObjectRequest; import com.google.storage.v2.RewriteObjectRequest; import com.google.storage.v2.StartResumableWriteRequest; import com.google.storage.v2.UpdateBucketRequest; @@ -123,6 +124,10 @@ public ResultRetryAlgorithm getFor(GetObjectRequest req) { return retryStrategy.getIdempotentHandler(); } + public ResultRetryAlgorithm getFor(RestoreObjectRequest req) { + return retryStrategy.getIdempotentHandler(); + } + public ResultRetryAlgorithm getFor(GetServiceAccountRequest req) { return retryStrategy.getIdempotentHandler(); } 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 53c73d4d5..e9857e93d 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 @@ -112,6 +112,7 @@ import com.google.storage.v2.Object; import com.google.storage.v2.ObjectAccessControl; import com.google.storage.v2.ReadObjectRequest; +import com.google.storage.v2.RestoreObjectRequest; import com.google.storage.v2.RewriteObjectRequest; import com.google.storage.v2.RewriteResponse; import com.google.storage.v2.StorageClient; @@ -403,6 +404,33 @@ public Blob get(BlobId blob) { return get(blob, new BlobGetOption[0]); } + @Override + public Blob restore(BlobId blob, BlobRestoreOption... options) { + Opts unwrap = Opts.unwrap(options); + return internalObjectRestore(blob, unwrap); + } + + private Blob internalObjectRestore(BlobId blobId, Opts opts) { + Opts finalOpts = opts.prepend(defaultOpts).prepend(ALL_BLOB_FIELDS); + GrpcCallContext grpcCallContext = + finalOpts.grpcMetadataMapper().apply(GrpcCallContext.createDefault()); + RestoreObjectRequest.Builder builder = + RestoreObjectRequest.newBuilder() + .setBucket(bucketNameCodec.encode(blobId.getBucket())) + .setObject(blobId.getName()); + ifNonNull(blobId.getGeneration(), builder::setGeneration); + RestoreObjectRequest req = finalOpts.restoreObjectRequest().apply(builder).build(); + GrpcCallContext merge = Utils.merge(grpcCallContext, Retrying.newCallContext()); + return Retrying.run( + getOptions(), + retryAlgorithmManager.getFor(req), + () -> storageClient.restoreObjectCallable().call(req, merge), + resp -> { + BlobInfo tmp = codecs.blobInfo().decode(resp); + return finalOpts.clearBlobFields().decode(tmp).asBlob(this); + }); + } + @Override public Page list(BucketListOption... options) { Opts opts = Opts.unwrap(options).prepend(defaultOpts).prepend(ALL_BUCKET_FIELDS); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/HttpRetryAlgorithmManager.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/HttpRetryAlgorithmManager.java index 22cac9a70..c5163ad00 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/HttpRetryAlgorithmManager.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/HttpRetryAlgorithmManager.java @@ -213,6 +213,11 @@ public ResultRetryAlgorithm getForObjectsGet( return retryStrategy.getIdempotentHandler(); } + public ResultRetryAlgorithm getForObjectsRestore( + StorageObject pb, Map optionsMap) { + return retryStrategy.getIdempotentHandler(); + } + public ResultRetryAlgorithm getForObjectsUpdate( StorageObject pb, Map optionsMap) { return optionsMap.containsKey(StorageRpc.Option.IF_METAGENERATION_MATCH) 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 c5add241d..7f84db77d 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.SOFT_DELETE_POLICY; import static com.google.cloud.storage.Utils.dateTimeCodec; import static com.google.cloud.storage.Utils.durationSecondsCodec; import static com.google.cloud.storage.Utils.ifNonNull; @@ -66,6 +67,7 @@ import com.google.cloud.storage.BucketInfo.Logging; import com.google.cloud.storage.BucketInfo.ObjectRetention; import com.google.cloud.storage.BucketInfo.PublicAccessPrevention; +import com.google.cloud.storage.BucketInfo.SoftDeletePolicy; import com.google.cloud.storage.Conversions.Codec; import com.google.cloud.storage.Cors.Origin; import com.google.cloud.storage.HmacKey.HmacKeyMetadata; @@ -119,6 +121,9 @@ final class JsonConversions { private final Codec objectRetentionCodec = Codec.of(this::objectRetentionEncode, this::objectRetentionDecode); + + private final Codec softDeletePolicyCodec = + Codec.of(this::softDeletePolicyEncode, this::softDeletePolicyDecode); private final Codec lifecycleRuleCodec = Codec.of(this::lifecycleRuleEncode, this::lifecycleRuleDecode); private final Codec lifecycleConditionCodec = @@ -251,6 +256,9 @@ private StorageObject blobInfoEncode(BlobInfo from) { dateTimeCodec::encode, to::setRetentionExpirationTime); + ifNonNull(from.getSoftDeleteTime(), dateTimeCodec::encode, to::setSoftDeleteTime); + ifNonNull(from.getHardDeleteTime(), dateTimeCodec::encode, to::setHardDeleteTime); + // todo: clean this up once retention is enabled in grpc // This is a workaround so that explicitly null retention objects are only included when the // user set an existing policy to null, to avoid sending any retention objects to the test @@ -332,6 +340,8 @@ private BlobInfo blobInfoDecode(StorageObject from) { dateTimeCodec::decode, to::setRetentionExpirationTimeOffsetDateTime); ifNonNull(from.getRetention(), this::retentionDecode, to::setRetention); + ifNonNull(from.getSoftDeleteTime(), dateTimeCodec::decode, to::setSoftDeleteTime); + ifNonNull(from.getHardDeleteTime(), dateTimeCodec::decode, to::setHardDeleteTime); return to.build(); } @@ -371,6 +381,21 @@ private Retention retentionDecode(StorageObject.Retention from) { return to.build(); } + private Bucket.SoftDeletePolicy softDeletePolicyEncode(SoftDeletePolicy from) { + Bucket.SoftDeletePolicy to = new Bucket.SoftDeletePolicy(); + ifNonNull( + from.getRetentionDuration(), durationSecondsCodec::encode, to::setRetentionDurationSeconds); + return to; + } + + private SoftDeletePolicy softDeletePolicyDecode(Bucket.SoftDeletePolicy from) { + SoftDeletePolicy.Builder to = SoftDeletePolicy.newBuilder(); + ifNonNull( + from.getRetentionDurationSeconds(), durationSecondsCodec::decode, to::setRetentionDuration); + ifNonNull(from.getEffectiveTime(), dateTimeCodec::decode, to::setEffectiveTime); + return to.build(); + } + private Bucket bucketInfoEncode(BucketInfo from) { Bucket to = new Bucket(); ifNonNull(from.getProject(), projectNameCodec::encode, p -> to.set(PROJECT_ID_FIELD_NAME, p)); @@ -441,6 +466,11 @@ private Bucket bucketInfoEncode(BucketInfo from) { this::customPlacementConfigEncode, to::setCustomPlacementConfig); ifNonNull(from.getObjectRetention(), this::objectRetentionEncode, to::setObjectRetention); + ifNonNull(from.getSoftDeletePolicy(), this::softDeletePolicyEncode, to::setSoftDeletePolicy); + if (from.getSoftDeletePolicy() == null + && from.getModifiedFields().contains(SOFT_DELETE_POLICY)) { + to.setSoftDeletePolicy(Data.nullOf(Bucket.SoftDeletePolicy.class)); + } ifNonNull( from.getHierarchicalNamespace(), this::hierarchicalNamespaceEncode, @@ -500,6 +530,7 @@ private BucketInfo bucketInfoDecode(com.google.api.services.storage.model.Bucket this::hierarchicalNamespaceDecode, to::setHierarchicalNamespace); ifNonNull(from.getObjectRetention(), this::objectRetentionDecode, to::setObjectRetention); + ifNonNull(from.getSoftDeletePolicy(), this::softDeletePolicyDecode, to::setSoftDeletePolicy); return to.build(); } 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 1d0ae8347..0f6b002d9 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 @@ -163,7 +163,10 @@ enum BucketField implements FieldSelector, NamedField { @TransportCompatibility({Transport.HTTP, Transport.GRPC}) HIERARCHICAL_NAMESPACE("hierarchicalNamespace", "hierarchical_namespace"), @TransportCompatibility({Transport.HTTP}) - OBJECT_RETENTION("objectRetention"); + OBJECT_RETENTION("objectRetention"), + + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + SOFT_DELETE_POLICY("softDeletePolicy", "soft_delete_policy"); static final List REQUIRED_FIELDS = ImmutableList.of(NAME); @@ -263,7 +266,13 @@ enum BlobField implements FieldSelector, NamedField { @TransportCompatibility({Transport.HTTP, Transport.GRPC}) CUSTOMER_ENCRYPTION("customerEncryption", "customer_encryption"), @TransportCompatibility({Transport.HTTP}) - RETENTION("retention"); + RETENTION("retention"), + + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + SOFT_DELETE_TIME("softDeleteTime", "soft_delete_time"), + + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + HARD_DELETE_TIME("hardDeleteTime", "hard_delete_time"); static final List REQUIRED_FIELDS = ImmutableList.of(BUCKET, NAME); @@ -1572,6 +1581,16 @@ public static BlobGetOption shouldReturnRawInputStream(boolean shouldReturnRawIn return new BlobGetOption(UnifiedOpts.returnRawInputStream(shouldReturnRawInputStream)); } + /** + * Returns an option for whether the request should return a soft-deleted object. If an object + * has been soft-deleted (Deleted while a Soft Delete Policy) is in place, this must be true or + * the request will return null. + */ + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + public static BlobGetOption softDeleted(boolean softDeleted) { + return new BlobGetOption(UnifiedOpts.softDeleted(softDeleted)); + } + /** * Deduplicate any options which are the same parameter. The value which comes last in {@code * os} will be the value included in the return. @@ -1607,6 +1626,61 @@ public static BlobGetOption[] dedupe(BlobGetOption[] array, BlobGetOption... os) } } + /** Class for specifying blob restore options * */ + class BlobRestoreOption extends Option { + + private static final long serialVersionUID = 1922118465380110958L; + + BlobRestoreOption(ObjectSourceOpt opt) { + super(opt); + } + + /** + * Returns an option for blob's data generation match. If this option is used the request will + * fail if generation does not match. + */ + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + public static BlobRestoreOption generationMatch(long generation) { + return new BlobRestoreOption(UnifiedOpts.generationMatch(generation)); + } + + /** + * Returns an option for blob's data generation mismatch. If this option is used the request + * will fail if blob's generation matches the provided value. + */ + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + public static BlobRestoreOption generationNotMatch(long generation) { + return new BlobRestoreOption(UnifiedOpts.generationNotMatch(generation)); + } + + /** + * Returns an option for blob's metageneration match. If this option is used the request will + * fail if blob's metageneration does not match the provided value. + */ + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + public static BlobRestoreOption metagenerationMatch(long generation) { + return new BlobRestoreOption(UnifiedOpts.metagenerationMatch(generation)); + } + + /** + * Returns an option for blob's metageneration mismatch. If this option is used the request will + * fail if blob's metageneration matches the provided value. + */ + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + public static BlobRestoreOption metagenerationNotMatch(long generation) { + return new BlobRestoreOption(UnifiedOpts.metagenerationNotMatch(generation)); + } + + /** + * Returns an option for whether the restored object should copy the access controls of the + * source object. + */ + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + public static BlobRestoreOption copySourceAcl(boolean copySourceAcl) { + return new BlobRestoreOption(UnifiedOpts.copySourceAcl(copySourceAcl)); + } + } + /** Class for specifying bucket list options. */ class BucketListOption extends Option { @@ -1838,6 +1912,12 @@ public static BlobListOption fields(BlobField... fields) { return new BlobListOption(UnifiedOpts.fields(set)); } + /** Returns an option for whether the list result should include soft-deleted objects. */ + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + public static BlobListOption softDeleted(boolean softDeleted) { + return new BlobListOption(UnifiedOpts.softDeleted(softDeleted)); + } + /** * Deduplicate any options which are the same parameter. The value which comes last in {@code * os} will be the value included in the return. @@ -3043,6 +3123,23 @@ Blob createFrom( @TransportCompatibility({Transport.HTTP, Transport.GRPC}) Blob get(BlobId blob); + /** + * Restores a soft-deleted object to full object status and returns the object. Note that you must + * specify a generation to use this method. + * + *

Example of restoring an object. + * + *

{@code
+   * String bucketName = "my-unique-bucket";
+   * String blobName = "my-blob-name";
+   * long generation = 42;
+   * BlobId blobId = BlobId.of(bucketName, blobName, gen);
+   * Blob blob = storage.restore(blobId);
+   * }
+ */ + @TransportCompatibility({Transport.HTTP, Transport.GRPC}) + Blob restore(BlobId blob, BlobRestoreOption... options); + /** * Lists the project's buckets. * 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 9af54fee2..a5df68b83 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 @@ -341,6 +341,24 @@ public Blob get(BlobId blob) { return get(blob, new BlobGetOption[0]); } + @Override + public Blob restore(BlobId blob, BlobRestoreOption... options) { + ImmutableMap optionsMap = + Opts.unwrap(options).resolveFrom(blob).getRpcOptions(); + + StorageObject obj = codecs.blobId().encode(blob); + + ResultRetryAlgorithm algorithm = retryAlgorithmManager.getForObjectsRestore(obj, optionsMap); + + return run( + algorithm, + () -> storageRpc.restore(obj, optionsMap), + (x) -> { + BlobInfo info = Conversions.json().blobInfo().decode(x); + return info.asBlob(this); + }); + } + private static class BucketPageFetcher implements NextPageFetcher { private static final long serialVersionUID = 8534413447247364038L; 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 3159cbebb..06909620d 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 @@ -53,6 +53,7 @@ import com.google.storage.v2.ListObjectsRequest; import com.google.storage.v2.LockBucketRetentionPolicyRequest; import com.google.storage.v2.ReadObjectRequest; +import com.google.storage.v2.RestoreObjectRequest; import com.google.storage.v2.RewriteObjectRequest; import com.google.storage.v2.UpdateBucketRequest; import com.google.storage.v2.UpdateHmacKeyRequest; @@ -157,6 +158,10 @@ default Mapper getObject() { default Mapper rewriteObject() { return Mapper.identity(); } + + default Mapper restoreObject() { + return Mapper.identity(); + } } /** @@ -482,6 +487,14 @@ static Projection projection(@NonNull String projection) { return new Projection(projection); } + static SoftDeleted softDeleted(boolean softDeleted) { + return new SoftDeleted(softDeleted); + } + + static CopySourceAcl copySourceAcl(boolean copySourceAcl) { + return new CopySourceAcl(copySourceAcl); + } + static RequestedPolicyVersion requestedPolicyVersion(long l) { return new RequestedPolicyVersion(l); } @@ -667,6 +680,40 @@ public Mapper listObjects() { } } + static final class SoftDeleted extends RpcOptVal + implements ObjectListOpt, ObjectSourceOpt { + + private static final long serialVersionUID = -8526951678111463350L; + + private SoftDeleted(boolean val) { + super(StorageRpc.Option.SOFT_DELETED, val); + } + + @Override + public Mapper listObjects() { + return b -> b.setSoftDeleted(val); + } + + @Override + public Mapper getObject() { + return b -> b.setSoftDeleted(val); + } + } + + static final class CopySourceAcl extends RpcOptVal implements ObjectSourceOpt { + + private static final long serialVersionUID = 2033755749149128119L; + + private CopySourceAcl(boolean val) { + super(StorageRpc.Option.COPY_SOURCE_ACL, val); + } + + @Override + public Mapper restoreObject() { + return b -> b.setCopySourceAcl(val); + } + } + static final class DisableGzipContent extends RpcOptVal<@NonNull Boolean> implements ObjectTargetOpt { private static final long serialVersionUID = 7445066765944965549L; @@ -1008,6 +1055,11 @@ public Mapper getObject() { return b -> b.setIfGenerationMatch(val); } + @Override + public Mapper restoreObject() { + return b -> b.setIfGenerationMatch(val); + } + @Override public Mapper updateObject() { return b -> b.setIfGenerationMatch(val); @@ -1064,6 +1116,11 @@ public Mapper getObject() { return b -> b.setIfGenerationNotMatch(val); } + @Override + public Mapper restoreObject() { + return b -> b.setIfGenerationNotMatch(val); + } + @Override public Mapper updateObject() { return b -> b.setIfGenerationNotMatch(val); @@ -1205,6 +1262,11 @@ public Mapper getObject() { return b -> b.setIfMetagenerationMatch(val); } + @Override + public Mapper restoreObject() { + return b -> b.setIfMetagenerationMatch(val); + } + @Override public Mapper updateObject() { return b -> b.setIfMetagenerationMatch(val); @@ -1285,6 +1347,11 @@ public Mapper getObject() { return b -> b.setIfMetagenerationNotMatch(val); } + @Override + public Mapper restoreObject() { + return b -> b.setIfMetagenerationNotMatch(val); + } + @Override public Mapper updateObject() { return b -> b.setIfMetagenerationNotMatch(val); @@ -2297,6 +2364,10 @@ Mapper getObjectsRequest() { return fuseMappers(ObjectSourceOpt.class, ObjectSourceOpt::getObject); } + Mapper restoreObjectRequest() { + return fuseMappers(ObjectSourceOpt.class, ObjectSourceOpt::restoreObject); + } + Mapper readObjectRequest() { return fuseMappers(ObjectSourceOpt.class, ObjectSourceOpt::readObject); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java index 3ca2eabec..8a9734271 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java @@ -459,6 +459,7 @@ public Tuple> list(final String bucket, Map storageObjects = @@ -541,7 +542,8 @@ private Storage.Objects.Get getCall(StorageObject object, Map options .setIfGenerationMatch(Option.IF_GENERATION_MATCH.getLong(options)) .setIfGenerationNotMatch(Option.IF_GENERATION_NOT_MATCH.getLong(options)) .setFields(Option.FIELDS.getString(options)) - .setUserProject(Option.USER_PROJECT.getString(options)); + .setUserProject(Option.USER_PROJECT.getString(options)) + .setSoftDeleted(Option.SOFT_DELETED.getBoolean(options)); } @Override @@ -563,6 +565,36 @@ public StorageObject get(StorageObject object, Map options) { } } + @Override + public StorageObject restore(StorageObject object, Map options) { + Span span = startSpan(HttpStorageRpcSpans.SPAN_NAME_RESTORE_OBJECT); + Scope scope = tracer.withSpan(span); + try { + Storage.Objects.Restore restore = + storage.objects().restore(object.getBucket(), object.getName(), object.getGeneration()); + return restore + .setProjection(DEFAULT_PROJECTION) + .setIfMetagenerationMatch(Option.IF_METAGENERATION_MATCH.getLong(options)) + .setIfMetagenerationNotMatch(Option.IF_METAGENERATION_NOT_MATCH.getLong(options)) + .setIfGenerationMatch(Option.IF_GENERATION_MATCH.getLong(options)) + .setIfGenerationNotMatch(Option.IF_GENERATION_NOT_MATCH.getLong(options)) + .setCopySourceAcl(Option.COPY_SOURCE_ACL.getBoolean(options)) + .setUserProject(Option.USER_PROJECT.getString(options)) + .setFields(Option.FIELDS.getString(options)) + .execute(); + } catch (IOException ex) { + span.setStatus(Status.UNKNOWN.withDescription(ex.getMessage())); + StorageException serviceException = translate(ex); + if (serviceException.getCode() == HTTP_NOT_FOUND) { + return null; + } + throw serviceException; + } finally { + scope.close(); + span.end(HttpStorageRpcSpans.END_SPAN_OPTIONS); + } + } + @Override public Bucket patch(Bucket bucket, Map options) { Span span = startSpan(HttpStorageRpcSpans.SPAN_NAME_PATCH_BUCKET); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java index 3f3d27d94..dc4b05336 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java @@ -30,6 +30,7 @@ class HttpStorageRpcSpans { static final String SPAN_NAME_LIST_OBJECTS = getTraceSpanName("list(String,Map)"); static final String SPAN_NAME_GET_BUCKET = getTraceSpanName("get(Bucket,Map)"); static final String SPAN_NAME_GET_OBJECT = getTraceSpanName("get(StorageObject,Map)"); + static final String SPAN_NAME_RESTORE_OBJECT = getTraceSpanName("restore(StorageObject, Map)"); static final String SPAN_NAME_PATCH_BUCKET = getTraceSpanName("patch(Bucket,Map)"); static final String SPAN_NAME_PATCH_OBJECT = getTraceSpanName("patch(StorageObject,Map)"); static final String SPAN_NAME_DELETE_BUCKET = getTraceSpanName("delete(Bucket,Map)"); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java index 3b40f6a23..d4e0abbff 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java @@ -74,8 +74,10 @@ enum Option { ENABLE_OBJECT_RETENTION("enableObjectRetention"), RETURN_RAW_INPUT_STREAM("returnRawInputStream"), OVERRIDE_UNLOCKED_RETENTION("overrideUnlockedRetention"), + SOFT_DELETED("softDeleted"), + COPY_SOURCE_ACL("copySourceAcl"), + GENERATION("generation"), INCLUDE_FOLDERS_AS_PREFIXES("includeFoldersAsPrefixes"); - ; private final String value; @@ -243,6 +245,13 @@ public int hashCode() { */ StorageObject get(StorageObject object, Map options); + /** + * If an object has been soft-deleted, restores it and returns the restored object.j + * + * @throws StorageException upon failure + */ + StorageObject restore(StorageObject object, Map options); + /** * Updates bucket information. * diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java index 97104634f..6686cb925 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java @@ -71,6 +71,11 @@ public StorageObject get(StorageObject object, Map options) { throw new UnsupportedOperationException("Not implemented yet"); } + @Override + public StorageObject restore(StorageObject object, Map options) { + throw new UnsupportedOperationException("Not implemented yet"); + } + @Override public Bucket patch(Bucket bucket, Map options) { throw new UnsupportedOperationException("Not implemented yet"); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobReadMaskTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobReadMaskTest.java index c2594a484..bf8c48258 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobReadMaskTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobReadMaskTest.java @@ -201,7 +201,9 @@ public ImmutableList parameters() { new Args<>(BlobField.UPDATED, LazyAssertion.equal()), new Args<>( BlobField.RETENTION, - LazyAssertion.skip("TODO: jesse fill in buganizer bug here"))); + LazyAssertion.skip("TODO: jesse fill in buganizer bug here")), + new Args<>(BlobField.SOFT_DELETE_TIME, LazyAssertion.equal()), + new Args<>(BlobField.HARD_DELETE_TIME, LazyAssertion.equal())); List argsDefined = args.stream().map(Args::getField).map(Enum::name).sorted().collect(Collectors.toList()); 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 9c9776032..c4c3c4059 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 @@ -40,6 +40,7 @@ import com.google.cloud.storage.it.runner.annotations.SingleBackend; import com.google.cloud.storage.it.runner.annotations.StorageFixture; import com.google.common.collect.ImmutableList; +import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -133,8 +134,27 @@ public ImmutableList parameters() { new Args<>(BucketField.TIME_CREATED, LazyAssertion.equal()), new Args<>(BucketField.UPDATED, LazyAssertion.equal()), new Args<>(BucketField.VERSIONING, LazyAssertion.equal()), - new Args<>(BucketField.HIERARCHICAL_NAMESPACE, LazyAssertion.equal()), - new Args<>(BucketField.WEBSITE, LazyAssertion.equal())); + new Args<>(BucketField.WEBSITE, LazyAssertion.equal()), + new Args<>( + BucketField.SOFT_DELETE_POLICY, + (jsonT, grpcT) -> { + assertThat( + jsonT + .getSoftDeletePolicy() + .getRetentionDuration() + .equals(grpcT.getSoftDeletePolicy().getRetentionDuration())); + assertThat( + jsonT + .getSoftDeletePolicy() + .getEffectiveTime() + .truncatedTo(ChronoUnit.SECONDS) + .equals( + grpcT + .getSoftDeletePolicy() + .getEffectiveTime() + .truncatedTo(ChronoUnit.SECONDS))); + }), + new Args<>(BucketField.HIERARCHICAL_NAMESPACE, LazyAssertion.equal())); List argsDefined = args.stream().map(Args::getField).map(Enum::name).sorted().collect(Collectors.toList()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java index 5b759be6b..97ab8ad3e 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBucketTest.java @@ -554,6 +554,67 @@ public void testUpdateBucket_noModification() throws Exception { } } + @Test + public void testSoftDeletePolicy() { + String bucketName = generator.randomBucketName(); + BucketInfo bucketInfo = + BucketInfo.newBuilder(bucketName) + .setSoftDeletePolicy( + BucketInfo.SoftDeletePolicy.newBuilder() + .setRetentionDuration(Duration.ofDays(10)) + .build()) + .build(); + try { + storage.create(bucketInfo); + + Bucket remoteBucket = storage.get(bucketName); + assertEquals(Duration.ofDays(10), remoteBucket.getSoftDeletePolicy().getRetentionDuration()); + assertNotNull(remoteBucket.getSoftDeletePolicy().getEffectiveTime()); + + String softDelBlobName = "softdelblob"; + remoteBucket.create(softDelBlobName, BLOB_BYTE_CONTENT); + + Blob blob = remoteBucket.get(softDelBlobName); + long gen = blob.getGeneration(); + + assertNull(blob.getSoftDeleteTime()); + assertNull(blob.getHardDeleteTime()); + + blob.delete(); + + assertNull(remoteBucket.get(softDelBlobName)); + + ImmutableList softDeletedBlobs = + ImmutableList.copyOf( + remoteBucket.list(Storage.BlobListOption.softDeleted(true)).iterateAll()); + assertThat(softDeletedBlobs.size() > 0); + + Blob softDeletedBlob = + remoteBucket.get(softDelBlobName, gen, Storage.BlobGetOption.softDeleted(true)); + + assertNotNull(softDeletedBlob); + assertNotNull(softDeletedBlob.getSoftDeleteTime()); + assertNotNull(softDeletedBlob.getHardDeleteTime()); + + assertNotNull(storage.restore(softDeletedBlob.getBlobId())); + + remoteBucket + .toBuilder() + .setSoftDeletePolicy( + BucketInfo.SoftDeletePolicy.newBuilder() + .setRetentionDuration(Duration.ofDays(20)) + .build()) + .build() + .update(); + + assertEquals( + Duration.ofDays(20), + storage.get(bucketName).getSoftDeletePolicy().getRetentionDuration()); + } finally { + BucketCleaner.doCleanup(bucketName, storage); + } + } + @Test public void createBucketWithHierarchicalNamespace() { String bucketName = generator.randomBucketName(); 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 7627bf3af..c7032ea61 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 @@ -326,6 +326,8 @@ public void storage_BucketGetOption_fields_BucketField() { "timeCreated", "updated", "versioning", + "website", + "softDeletePolicy", "hierarchicalNamespace", "website"); s.get( @@ -739,7 +741,9 @@ public void storage_BlobGetOption_fields_BlobField() { "timeDeleted", "timeStorageClassUpdated", "updated", - "retention"); + "retention", + "softDeleteTime", + "hardDeleteTime"); s.get(o.getBlobId(), BlobGetOption.fields(BlobField.values())); requestAuditing.assertQueryParam("fields", expected, splitOnCommaToSet()); } @@ -817,6 +821,8 @@ public void storage_BucketListOption_fields_BucketField() { "items/timeCreated", "items/updated", "items/versioning", + "items/website", + "items/softDeletePolicy", "items/hierarchicalNamespace", "items/website"); s.list(BucketListOption.fields(TestUtils.filterOutHttpOnlyBucketFields(BucketField.values()))); @@ -915,7 +921,9 @@ public void storage_BlobListOption_fields_BlobField() { "items/timeDeleted", "items/timeStorageClassUpdated", "items/updated", - "items/retention"); + "items/retention", + "items/softDeleteTime", + "items/hardDeleteTime"); s.list(b.getName(), BlobListOption.fields(BlobField.values())); requestAuditing.assertQueryParam("fields", expected, splitOnCommaToSet()); } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/AbstractStorageProxy.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/AbstractStorageProxy.java index d264e5a6d..9e5e9691e 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/AbstractStorageProxy.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/AbstractStorageProxy.java @@ -139,6 +139,11 @@ public Blob get(BlobId blob) { return delegate.get(blob); } + @Override + public Blob restore(BlobId blob, BlobRestoreOption... options) { + return delegate.restore(blob, options); + } + @Override public Page list(BucketListOption... options) { return delegate.list(options); From 110b80cdde24da4868e46c3909020db7b02d5491 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 15 Mar 2024 17:59:27 +0100 Subject: [PATCH 11/14] deps: update dependency net.jqwik:jqwik to v1.8.4 (#2447) --- 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 604b126fb..0004206f4 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -248,7 +248,7 @@ net.jqwik jqwik - 1.8.3 + 1.8.4 test From 12c9db8935f25a5f9e4633af85ea96acaa914d23 Mon Sep 17 00:00:00 2001 From: Sydney Munro <97561403+sydney-munro@users.noreply.github.com> Date: Fri, 15 Mar 2024 11:13:45 -0700 Subject: [PATCH 12/14] fix: Fix name digest for noprefix (#2448) --- .../ParallelCompositeUploadBlobWriteSessionConfig.java | 5 ++++- .../ParallelCompositeUploadBlobWriteSessionConfigTest.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfig.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfig.java index b877d82d9..e13f54964 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfig.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfig.java @@ -612,7 +612,10 @@ public NoPrefix(SecureRandom rand) { } @Override - protected String fmtFields(String randomKey, String nameDigest, String partRange) { + protected String fmtFields(String randomKey, String ultimateObjectName, String partRange) { + HashCode hashCode = + OBJECT_NAME_HASH_FUNCTION.hashString(ultimateObjectName, StandardCharsets.UTF_8); + String nameDigest = B64.encodeToString(hashCode.asBytes()); return randomKey + FIELD_SEPARATOR // todo: do we want to diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfigTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfigTest.java index 86eddc5b9..465741a7d 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfigTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfigTest.java @@ -84,7 +84,7 @@ public void partNameStrategy_objectNamePrefix() throws Exception { // name digest () -> assertField(fmt, 1).hasLength(22), () -> assertField(fmt, 2).isEqualTo("0001-0096.part"), - () -> assertThat(fmt).startsWith("a/b/obj/")); + () -> assertThat(fmt).startsWith("a/b/obj")); } private static StringSubject assertField(String fmt, int idx) { From 43b800645ba3622e5de635825e1d082c6d26c2eb Mon Sep 17 00:00:00 2001 From: Sydney Munro <97561403+sydney-munro@users.noreply.github.com> Date: Fri, 15 Mar 2024 11:49:08 -0700 Subject: [PATCH 13/14] feat: Add Custom Part Metadata Decorator to ParallelCompositeUploadConfig (#2434) --- ...CompositeUploadBlobWriteSessionConfig.java | 139 ++++++++++++++++-- ...lelCompositeUploadWritableByteChannel.java | 5 + ...ositeUploadBlobWriteSessionConfigTest.java | 17 +++ ...ompositeUploadWritableByteChannelTest.java | 63 +++++++- .../cloud/storage/SerializationTest.java | 10 +- .../com/google/cloud/storage/TestClock.java | 2 +- ...ositeUploadBlobWriteSessionConfigTest.java | 19 ++- 7 files changed, 241 insertions(+), 14 deletions(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfig.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfig.java index e13f54964..07551abe4 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfig.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfig.java @@ -42,12 +42,15 @@ import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.time.Clock; +import java.time.Duration; +import java.time.OffsetDateTime; import java.util.Base64; import java.util.Base64.Encoder; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.UnaryOperator; import javax.annotation.concurrent.Immutable; import org.checkerframework.checker.nullness.qual.NonNull; @@ -125,18 +128,21 @@ public final class ParallelCompositeUploadBlobWriteSessionConfig extends BlobWri private final BufferAllocationStrategy bufferAllocationStrategy; private final PartNamingStrategy partNamingStrategy; private final PartCleanupStrategy partCleanupStrategy; + private final PartMetadataFieldDecorator partMetadataFieldDecorator; private ParallelCompositeUploadBlobWriteSessionConfig( int maxPartsPerCompose, ExecutorSupplier executorSupplier, BufferAllocationStrategy bufferAllocationStrategy, PartNamingStrategy partNamingStrategy, - PartCleanupStrategy partCleanupStrategy) { + PartCleanupStrategy partCleanupStrategy, + PartMetadataFieldDecorator partMetadataFieldDecorator) { this.maxPartsPerCompose = maxPartsPerCompose; this.executorSupplier = executorSupplier; this.bufferAllocationStrategy = bufferAllocationStrategy; this.partNamingStrategy = partNamingStrategy; this.partCleanupStrategy = partCleanupStrategy; + this.partMetadataFieldDecorator = partMetadataFieldDecorator; } @InternalApi @@ -150,7 +156,8 @@ ParallelCompositeUploadBlobWriteSessionConfig withMaxPartsPerCompose(int maxPart executorSupplier, bufferAllocationStrategy, partNamingStrategy, - partCleanupStrategy); + partCleanupStrategy, + partMetadataFieldDecorator); } /** @@ -170,7 +177,8 @@ public ParallelCompositeUploadBlobWriteSessionConfig withExecutorSupplier( executorSupplier, bufferAllocationStrategy, partNamingStrategy, - partCleanupStrategy); + partCleanupStrategy, + partMetadataFieldDecorator); } /** @@ -191,7 +199,8 @@ public ParallelCompositeUploadBlobWriteSessionConfig withBufferAllocationStrateg executorSupplier, bufferAllocationStrategy, partNamingStrategy, - partCleanupStrategy); + partCleanupStrategy, + partMetadataFieldDecorator); } /** @@ -211,7 +220,8 @@ public ParallelCompositeUploadBlobWriteSessionConfig withPartNamingStrategy( executorSupplier, bufferAllocationStrategy, partNamingStrategy, - partCleanupStrategy); + partCleanupStrategy, + partMetadataFieldDecorator); } /** @@ -231,7 +241,29 @@ public ParallelCompositeUploadBlobWriteSessionConfig withPartCleanupStrategy( executorSupplier, bufferAllocationStrategy, partNamingStrategy, - partCleanupStrategy); + partCleanupStrategy, + partMetadataFieldDecorator); + } + + /** + * Specify a Part Metadata Field decorator, this will manipulate the metadata associated with part + * objects, the ultimate object metadata will remain unchanged. + * + *

Default: {@link PartMetadataFieldDecorator#noOp()} + * + * @since 2.36.0 This new api is in preview and is subject to breaking changes. + */ + @BetaApi + public ParallelCompositeUploadBlobWriteSessionConfig withPartMetadataFieldDecorator( + PartMetadataFieldDecorator partMetadataFieldDecorator) { + checkNotNull(partMetadataFieldDecorator, "partMetadataFieldDecorator must be non null"); + return new ParallelCompositeUploadBlobWriteSessionConfig( + maxPartsPerCompose, + executorSupplier, + bufferAllocationStrategy, + partNamingStrategy, + partCleanupStrategy, + partMetadataFieldDecorator); } @BetaApi @@ -241,7 +273,8 @@ static ParallelCompositeUploadBlobWriteSessionConfig withDefaults() { ExecutorSupplier.cachedPool(), BufferAllocationStrategy.simple(ByteSizeConstants._16MiB), PartNamingStrategy.noPrefix(), - PartCleanupStrategy.always()); + PartCleanupStrategy.always(), + PartMetadataFieldDecorator.noOp()); } @InternalApi @@ -249,7 +282,10 @@ static ParallelCompositeUploadBlobWriteSessionConfig withDefaults() { WriterFactory createFactory(Clock clock) throws IOException { Executor executor = executorSupplier.get(); BufferHandlePool bufferHandlePool = bufferAllocationStrategy.get(); - return new ParallelCompositeUploadWriterFactory(clock, executor, bufferHandlePool); + PartMetadataFieldDecoratorInstance partMetadataFieldDecoratorInstance = + partMetadataFieldDecorator.newInstance(clock); + return new ParallelCompositeUploadWriterFactory( + clock, executor, bufferHandlePool, partMetadataFieldDecoratorInstance); } /** @@ -277,6 +313,7 @@ private BufferAllocationStrategy() {} */ @BetaApi public static BufferAllocationStrategy simple(int capacity) { + checkArgument(capacity > 0, "bufferCapacity must be > 0"); return new SimpleBufferAllocationStrategy(capacity); } @@ -291,6 +328,8 @@ public static BufferAllocationStrategy simple(int capacity) { */ @BetaApi public static BufferAllocationStrategy fixedPool(int bufferCount, int bufferCapacity) { + checkArgument(bufferCount > 0, "bufferCount must be > 0"); + checkArgument(bufferCapacity > 0, "bufferCapacity must be > 0"); return new FixedPoolBufferAllocationStrategy(bufferCount, bufferCapacity); } @@ -361,6 +400,7 @@ public static ExecutorSupplier cachedPool() { */ @BetaApi public static ExecutorSupplier fixedPool(int poolSize) { + checkArgument(poolSize > 0, "poolSize must be > 0"); return new FixedSupplier(poolSize); } @@ -631,6 +671,79 @@ protected String fmtFields(String randomKey, String ultimateObjectName, String p } } + /** + * A Decorator which is used to manipulate metadata fields, specifically on the part objects + * created in a Parallel Composite Upload + * + * @see #withPartMetadataFieldDecorator(PartMetadataFieldDecorator) + * @since 2.36.0 This new api is in preview and is subject to breaking changes. + */ + @BetaApi + @Immutable + public abstract static class PartMetadataFieldDecorator implements Serializable { + + abstract PartMetadataFieldDecoratorInstance newInstance(Clock clock); + + /** + * A decorator that is used to manipulate the Custom Time Metadata field of part files. {@link + * BlobInfo#getCustomTimeOffsetDateTime()} + * + *

When provided with a duration, a time in the future will be calculated for each part + * object upon upload, this new value can be used in OLM rules to cleanup abandoned part files. + * + *

See [CustomTime OLM + * documentation](https://cloud.google.com/storage/docs/lifecycle#dayssincecustomtime) + * + * @see #withPartMetadataFieldDecorator(PartMetadataFieldDecorator) + * @since 2.36.0 This new api is in preview and is subject to breaking changes. + */ + @BetaApi + public static PartMetadataFieldDecorator setCustomTimeInFuture(Duration timeInFuture) { + checkNotNull(timeInFuture, "timeInFuture must not be null"); + return new CustomTimeInFuture(timeInFuture); + } + + @BetaApi + public static PartMetadataFieldDecorator noOp() { + return NoOp.INSTANCE; + } + + @BetaApi + private static final class CustomTimeInFuture extends PartMetadataFieldDecorator { + private static final long serialVersionUID = -6213742554954751892L; + private final Duration duration; + + CustomTimeInFuture(Duration duration) { + this.duration = duration; + } + + @Override + PartMetadataFieldDecoratorInstance newInstance(Clock clock) { + return builder -> { + OffsetDateTime futureTime = + OffsetDateTime.from( + clock.instant().plus(duration).atZone(clock.getZone()).toOffsetDateTime()); + return builder.setCustomTimeOffsetDateTime(futureTime); + }; + } + } + + private static final class NoOp extends PartMetadataFieldDecorator { + private static final long serialVersionUID = -4569486383992999205L; + private static final NoOp INSTANCE = new NoOp(); + + @Override + PartMetadataFieldDecoratorInstance newInstance(Clock clock) { + return builder -> builder; + } + + /** prevent java serialization from using a new instance */ + private Object readResolve() { + return INSTANCE; + } + } + } + /** * A cleanup strategy which will dictate what cleanup operations are performed automatically when * performing a parallel composite upload. @@ -708,6 +821,8 @@ public static PartCleanupStrategy never() { } } + interface PartMetadataFieldDecoratorInstance extends UnaryOperator {} + private abstract static class Factory implements Serializable { private static final long serialVersionUID = 271806144227661056L; @@ -721,12 +836,17 @@ private class ParallelCompositeUploadWriterFactory implements WriterFactory { private final Clock clock; private final Executor executor; private final BufferHandlePool bufferHandlePool; + private final PartMetadataFieldDecoratorInstance partMetadataFieldDecoratorInstance; private ParallelCompositeUploadWriterFactory( - Clock clock, Executor executor, BufferHandlePool bufferHandlePool) { + Clock clock, + Executor executor, + BufferHandlePool bufferHandlePool, + PartMetadataFieldDecoratorInstance partMetadataFieldDecoratorInstance) { this.clock = clock; this.executor = executor; this.bufferHandlePool = bufferHandlePool; + this.partMetadataFieldDecoratorInstance = partMetadataFieldDecoratorInstance; } @Override @@ -760,6 +880,7 @@ public ApiFuture openAsync() { partNamingStrategy, partCleanupStrategy, maxPartsPerCompose, + partMetadataFieldDecoratorInstance, result, storageInternal, info, diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadWritableByteChannel.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadWritableByteChannel.java index 9ff1ebdb5..639802cde 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadWritableByteChannel.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/ParallelCompositeUploadWritableByteChannel.java @@ -31,6 +31,7 @@ import com.google.cloud.storage.BufferedWritableByteChannelSession.BufferedWritableByteChannel; import com.google.cloud.storage.MetadataField.PartRange; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartCleanupStrategy; +import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartMetadataFieldDecoratorInstance; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartNamingStrategy; import com.google.cloud.storage.Storage.ComposeRequest; import com.google.cloud.storage.UnifiedOpts.Crc32cMatch; @@ -111,6 +112,7 @@ final class ParallelCompositeUploadWritableByteChannel implements BufferedWritab private final PartNamingStrategy partNamingStrategy; private final PartCleanupStrategy partCleanupStrategy; private final int maxElementsPerCompact; + private final PartMetadataFieldDecoratorInstance partMetadataFieldDecorator; private final SettableApiFuture finalObject; private final StorageInternal storage; private final BlobInfo ultimateObject; @@ -135,6 +137,7 @@ final class ParallelCompositeUploadWritableByteChannel implements BufferedWritab PartNamingStrategy partNamingStrategy, PartCleanupStrategy partCleanupStrategy, int maxElementsPerCompact, + PartMetadataFieldDecoratorInstance partMetadataFieldDecorator, SettableApiFuture finalObject, StorageInternal storage, BlobInfo ultimateObject, @@ -144,6 +147,7 @@ final class ParallelCompositeUploadWritableByteChannel implements BufferedWritab this.partNamingStrategy = partNamingStrategy; this.partCleanupStrategy = partCleanupStrategy; this.maxElementsPerCompact = maxElementsPerCompact; + this.partMetadataFieldDecorator = partMetadataFieldDecorator; this.finalObject = finalObject; this.storage = storage; this.ultimateObject = ultimateObject; @@ -427,6 +431,7 @@ private BlobInfo definePart(BlobInfo ultimateObject, PartRange partRange, long o PART_INDEX.appendTo(partRange, builder); OBJECT_OFFSET.appendTo(offset, builder); b.setMetadata(builder.build()); + b = partMetadataFieldDecorator.apply(b); return b.build(); } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfigTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfigTest.java index 465741a7d..3ef553727 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfigTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ParallelCompositeUploadBlobWriteSessionConfigTest.java @@ -21,8 +21,13 @@ import static com.google.common.truth.Truth.assertWithMessage; import com.google.cloud.storage.MetadataField.PartRange; +import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartMetadataFieldDecorator; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartNamingStrategy; import com.google.common.truth.StringSubject; +import java.time.Duration; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; import org.junit.Test; public final class ParallelCompositeUploadBlobWriteSessionConfigTest { @@ -87,6 +92,18 @@ public void partNameStrategy_objectNamePrefix() throws Exception { () -> assertThat(fmt).startsWith("a/b/obj")); } + @Test + public void partMetadataFieldDecorator_customTime() { + BlobInfo.Builder testBlob = BlobInfo.newBuilder("testBlob", "testBucket"); + Duration duration = Duration.ofSeconds(30); + TestClock clock = TestClock.tickBy(Instant.EPOCH, Duration.ofSeconds(1)); + OffsetDateTime expected = + OffsetDateTime.from(Instant.EPOCH.plus(duration).atZone(ZoneId.of("Z"))); + PartMetadataFieldDecorator.setCustomTimeInFuture(duration).newInstance(clock).apply(testBlob); + + assertThat(expected).isEqualTo(testBlob.build().getCustomTimeOffsetDateTime()); + } + private static StringSubject assertField(String fmt, int idx) { String[] split = fmt.split(";"); String s = split[idx]; 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 ed66a3f17..3a78adf4f 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 @@ -29,6 +29,8 @@ import com.google.cloud.storage.Crc32cValue.Crc32cLengthKnown; import com.google.cloud.storage.MetadataField.PartRange; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartCleanupStrategy; +import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartMetadataFieldDecorator; +import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartMetadataFieldDecoratorInstance; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartNamingStrategy; import com.google.cloud.storage.ParallelCompositeUploadWritableByteChannel.BufferHandleReleaser; import com.google.cloud.storage.Storage.ComposeRequest; @@ -47,9 +49,14 @@ import com.google.common.util.concurrent.Uninterruptibles; import com.google.storage.v2.WriteObjectRequest; import io.grpc.Status.Code; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousCloseException; import java.nio.channels.ClosedChannelException; +import java.time.Duration; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Base64; import java.util.Collections; @@ -80,6 +87,7 @@ public final class ParallelCompositeUploadWritableByteChannelTest { private SettableApiFuture finalObject; private FakeStorageInternal storageInternal; private SimplisticPartNamingStrategy partNamingStrategy; + private PartMetadataFieldDecoratorInstance partMetadataFieldDecorator; private int bufferCapacity; @Before @@ -91,6 +99,7 @@ public void setUp() throws Exception { finalObject = SettableApiFuture.create(); partNamingStrategy = new SimplisticPartNamingStrategy("prefix"); storageInternal = new FakeStorageInternal(); + partMetadataFieldDecorator = PartMetadataFieldDecorator.noOp().newInstance(null); } @Test @@ -202,6 +211,7 @@ public void cleanup_success_disabled() throws Exception { partNamingStrategy, PartCleanupStrategy.never(), maxElementsPerCompact, + partMetadataFieldDecorator, finalObject, storageInternal, info, @@ -241,6 +251,7 @@ public void writeDoesNotFlushIfItIsnNotFull() throws Exception { partNamingStrategy, PartCleanupStrategy.never(), maxElementsPerCompact, + partMetadataFieldDecorator, finalObject, storageInternal, info, @@ -340,6 +351,7 @@ public void partsRetainMetadata() throws Exception { partNamingStrategy, PartCleanupStrategy.never(), 3, + partMetadataFieldDecorator, finalObject, new FakeStorageInternal() { @Override @@ -429,6 +441,7 @@ public void creatingAnEmptyObjectWhichFailsIsSetAsResultFailureAndThrowFromClose partNamingStrategy, PartCleanupStrategy.always(), 3, + partMetadataFieldDecorator, finalObject, new FakeStorageInternal() { @Override @@ -462,6 +475,7 @@ public void badServerCrc32cResultsInException() throws Exception { partNamingStrategy, PartCleanupStrategy.always(), 3, + partMetadataFieldDecorator, finalObject, new FakeStorageInternal() { @Override @@ -568,6 +582,7 @@ public BlobInfo internalDirectUpload( partNamingStrategy, PartCleanupStrategy.never(), 32, + partMetadataFieldDecorator, finalObject, storageInternal, info, @@ -647,6 +662,7 @@ public void errorContextIsPopulated() throws Exception { partNamingStrategy, PartCleanupStrategy.never(), 3, + partMetadataFieldDecorator, finalObject, new FakeStorageInternal() { @Override @@ -729,6 +745,7 @@ public BlobInfo internalObjectGet(BlobId blobId, Opts opts) { partNamingStrategy, PartCleanupStrategy.always(), 10, + partMetadataFieldDecorator, finalObject, storageInternal, info, @@ -749,6 +766,49 @@ public BlobInfo internalObjectGet(BlobId blobId, Opts opts) { () -> assertThat(storageInternal.deleteRequests).containsExactly(p1, p2, p3)); } + @Test + public void partMetadataFieldDecoratorUsesCustomTime() throws IOException { + TestClock clock = TestClock.tickBy(Instant.EPOCH, Duration.ofSeconds(1)); + OffsetDateTime rangeBegin = + OffsetDateTime.from(Instant.EPOCH.plus(Duration.ofSeconds(29)).atZone(ZoneId.of("Z"))); + OffsetDateTime rangeEnd = + OffsetDateTime.from(Instant.EPOCH.plus(Duration.ofMinutes(2)).atZone(ZoneId.of("Z"))); + + FakeStorageInternal storageInternal = + new FakeStorageInternal() { + @Override + public BlobInfo internalDirectUpload( + BlobInfo info, Opts opts, ByteBuffer buf) { + if (info.getBlobId().getName().endsWith(".part")) { + // Kinda hacky but since we are creating multiple parts we will use a range + // to ensure the customTimes are being calculated appropriately + assertThat(info.getCustomTimeOffsetDateTime().isAfter(rangeBegin)).isTrue(); + assertThat(info.getCustomTimeOffsetDateTime().isBefore(rangeEnd)).isTrue(); + } else { + assertThat(info.getCustomTimeOffsetDateTime()).isNull(); + } + return super.internalDirectUpload(info, opts, buf); + } + }; + ParallelCompositeUploadWritableByteChannel pcu = + new ParallelCompositeUploadWritableByteChannel( + bufferHandlePool, + MoreExecutors.directExecutor(), + partNamingStrategy, + PartCleanupStrategy.always(), + 10, + PartMetadataFieldDecorator.setCustomTimeInFuture(Duration.ofSeconds(30)) + .newInstance(clock), + finalObject, + storageInternal, + info, + opts); + byte[] bytes = DataGenerator.base64Characters().genBytes(bufferCapacity * 3 - 1); + pcu.write(ByteBuffer.wrap(bytes)); + + pcu.close(); + } + @NonNull private ParallelCompositeUploadWritableByteChannel defaultPcu(int maxElementsPerCompact) { return new ParallelCompositeUploadWritableByteChannel( @@ -757,6 +817,7 @@ private ParallelCompositeUploadWritableByteChannel defaultPcu(int maxElementsPer partNamingStrategy, PartCleanupStrategy.always(), maxElementsPerCompact, + partMetadataFieldDecorator, finalObject, storageInternal, info, @@ -773,7 +834,7 @@ private static class FakeStorageInternal implements StorageInternal { protected final List composeRequests; protected final List deleteRequests; - private FakeStorageInternal() { + FakeStorageInternal() { generations = new AtomicInteger(1); addedObjects = Collections.synchronizedMap(new HashMap<>()); composeRequests = Collections.synchronizedList(new ArrayList<>()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/SerializationTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/SerializationTest.java index eab0e78ed..5f642b50b 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/SerializationTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/SerializationTest.java @@ -36,6 +36,7 @@ import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.BufferAllocationStrategy; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.ExecutorSupplier; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartCleanupStrategy; +import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartMetadataFieldDecorator; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartNamingStrategy; import com.google.cloud.storage.Storage.BlobTargetOption; import com.google.cloud.storage.Storage.BucketField; @@ -55,6 +56,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.time.Duration; import java.util.Base64; import java.util.Collections; import java.util.Map; @@ -388,10 +390,16 @@ public void blobWriteSessionConfig_pcu() throws IOException, ClassNotFoundExcept .withBufferAllocationStrategy(BufferAllocationStrategy.fixedPool(1, 3)) .withPartCleanupStrategy(PartCleanupStrategy.never()) .withPartNamingStrategy(PartNamingStrategy.prefix("prefix")) - .withExecutorSupplier(ExecutorSupplier.fixedPool(5)); + .withExecutorSupplier(ExecutorSupplier.fixedPool(5)) + .withPartMetadataFieldDecorator( + PartMetadataFieldDecorator.setCustomTimeInFuture(Duration.ofMinutes(10))); ParallelCompositeUploadBlobWriteSessionConfig pcu2copy = serializeAndDeserialize(pcu2); assertThat(pcu2copy).isNotNull(); + PartMetadataFieldDecorator noop = PartMetadataFieldDecorator.noOp(); + PartMetadataFieldDecorator noopCopy = serializeAndDeserialize(noop); + assertThat(noopCopy).isSameInstanceAs(noop); + InvalidClassException invalidClassException = assertThrows( InvalidClassException.class, diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/TestClock.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/TestClock.java index e37a4f024..89d04c35c 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/TestClock.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/TestClock.java @@ -37,7 +37,7 @@ private TestClock(Instant begin, UnaryOperator next) { @Override public ZoneId getZone() { - throw new UnsupportedOperationException("TestClock.getZone()"); + return ZoneId.of("Z"); } @Override diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITParallelCompositeUploadBlobWriteSessionConfigTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITParallelCompositeUploadBlobWriteSessionConfigTest.java index 012a700f6..304cdd69f 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITParallelCompositeUploadBlobWriteSessionConfigTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITParallelCompositeUploadBlobWriteSessionConfigTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertThrows; +import com.google.api.gax.paging.Page; import com.google.api.gax.rpc.ApiExceptions; import com.google.cloud.kms.v1.CryptoKey; import com.google.cloud.storage.Blob; @@ -34,6 +35,7 @@ import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.BufferAllocationStrategy; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.ExecutorSupplier; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartCleanupStrategy; +import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartMetadataFieldDecorator; import com.google.cloud.storage.ParallelCompositeUploadBlobWriteSessionConfig.PartNamingStrategy; import com.google.cloud.storage.Storage; import com.google.cloud.storage.Storage.BlobSourceOption; @@ -57,6 +59,7 @@ import java.nio.channels.AsynchronousCloseException; import java.nio.channels.WritableByteChannel; import java.security.Key; +import java.time.Duration; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -109,8 +112,11 @@ public void setUp() throws Exception { // define a max part size that is fairly small to aid in test speed .withBufferAllocationStrategy(BufferAllocationStrategy.simple(_1MiB)) .withPartNamingStrategy(PartNamingStrategy.prefix("prefix-a")) - // let our fixtures take care of cleaning things up if an upload fails - .withPartCleanupStrategy(PartCleanupStrategy.onlyOnSuccess()); + // Write customTime 30 seconds in the future + .withPartMetadataFieldDecorator( + PartMetadataFieldDecorator.setCustomTimeInFuture(Duration.ofSeconds(30))) + // let our fixtures take care of cleaning things + .withPartCleanupStrategy(PartCleanupStrategy.never()); StorageOptions storageOptions = null; if (transport == Transport.GRPC) { @@ -140,6 +146,15 @@ public static void afterClass() { } } + @Test + public void partFilesCreatedWithCustomTimeWritten() throws IOException { + doTest(bucket, 10 * _1MiB + 37, ImmutableList.of(), ImmutableList.of(), ImmutableList.of()); + Page blobs = storage.list(bucket.getName(), Storage.BlobListOption.prefix("prefix-a")); + for (Blob blob : blobs.iterateAll()) { + assertThat(blob.getCustomTimeOffsetDateTime()).isNotNull(); + } + } + @Test public void errorRaisedByMethodAndFutureResult() throws IOException { From 838f9f86edb674aa3352ba2f6c6011bc2f5c5ea7 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:29:17 -0700 Subject: [PATCH 14/14] chore(main): release 2.36.0 (#2443) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(main): release 2.36.0 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Owl Bot --- CHANGELOG.md | 22 +++++++++++++++++++ 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 | 2 +- storage-shared-benchmarking/pom.xml | 4 ++-- versions.txt | 14 ++++++------ 13 files changed, 62 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bac6556a3..e2eb26d4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [2.36.0](https://github.com/googleapis/java-storage/compare/v2.35.0...v2.36.0) (2024-03-15) + + +### Features + +* Add Custom Part Metadata Decorator to ParallelCompositeUploadConfig ([#2434](https://github.com/googleapis/java-storage/issues/2434)) ([43b8006](https://github.com/googleapis/java-storage/commit/43b800645ba3622e5de635825e1d082c6d26c2eb)) +* Add hierarchical namespace and folders features ([#2445](https://github.com/googleapis/java-storage/issues/2445)) ([8074fff](https://github.com/googleapis/java-storage/commit/8074fffed5208a8578e5afe694fdd3d8df627b8c)) +* Add soft delete feature ([#2403](https://github.com/googleapis/java-storage/issues/2403)) ([989f36f](https://github.com/googleapis/java-storage/commit/989f36fbb206832a6a3584c77546d3d560ac0df8)) + + +### Bug Fixes + +* Fix name digest for noprefix ([#2448](https://github.com/googleapis/java-storage/issues/2448)) ([12c9db8](https://github.com/googleapis/java-storage/commit/12c9db8935f25a5f9e4633af85ea96acaa914d23)) +* Missing serialVersionUID of serializable classes ([#2344](https://github.com/googleapis/java-storage/issues/2344)) ([736865b](https://github.com/googleapis/java-storage/commit/736865b4b97aa3940e1eab6a582d0ef38db31bba)) + + +### Dependencies + +* Update dependency com.google.apis:google-api-services-storage to v1-rev20240307-2.0.0 ([#2442](https://github.com/googleapis/java-storage/issues/2442)) ([1352203](https://github.com/googleapis/java-storage/commit/1352203859c3798423ef78823ed10577b93eebef)) +* Update dependency net.jqwik:jqwik to v1.8.4 ([#2447](https://github.com/googleapis/java-storage/issues/2447)) ([110b80c](https://github.com/googleapis/java-storage/commit/110b80cdde24da4868e46c3909020db7b02d5491)) +* Update gcr.io/cloud-devrel-public-resources/storage-testbench docker tag to v0.42.0 ([#2441](https://github.com/googleapis/java-storage/issues/2441)) ([80745d4](https://github.com/googleapis/java-storage/commit/80745d415810353b3466a3eda12f6ca50a2c71b0)) + ## [2.35.0](https://github.com/googleapis/java-storage/compare/v2.34.0...v2.35.0) (2024-03-04) diff --git a/gapic-google-cloud-storage-v2/pom.xml b/gapic-google-cloud-storage-v2/pom.xml index d02b72dd1..5e15e2a90 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.35.1-alpha-SNAPSHOT + 2.36.0-alpha gapic-google-cloud-storage-v2 GRPC library for gapic-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.35.1-SNAPSHOT + 2.36.0 diff --git a/google-cloud-storage-bom/pom.xml b/google-cloud-storage-bom/pom.xml index bc0311201..f0489d5a3 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.35.1-SNAPSHOT + 2.36.0 pom com.google.cloud @@ -69,37 +69,37 @@ com.google.cloud google-cloud-storage - 2.35.1-SNAPSHOT + 2.36.0 com.google.api.grpc gapic-google-cloud-storage-v2 - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha com.google.api.grpc grpc-google-cloud-storage-v2 - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha com.google.api.grpc proto-google-cloud-storage-v2 - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha com.google.cloud google-cloud-storage-control - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha com.google.api.grpc grpc-google-cloud-storage-control-v2 - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha com.google.api.grpc proto-google-cloud-storage-control-v2 - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha diff --git a/google-cloud-storage-control/pom.xml b/google-cloud-storage-control/pom.xml index 747b2b3d7..7663e73a6 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.35.1-alpha-SNAPSHOT + 2.36.0-alpha google-cloud-storage-control GRPC library for google-cloud-storage-control com.google.cloud google-cloud-storage-parent - 2.35.1-SNAPSHOT + 2.36.0 diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml index 0004206f4..35f4cd2b0 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -2,7 +2,7 @@ 4.0.0 google-cloud-storage - 2.35.1-SNAPSHOT + 2.36.0 jar Google Cloud Storage https://github.com/googleapis/java-storage @@ -12,7 +12,7 @@ com.google.cloud google-cloud-storage-parent - 2.35.1-SNAPSHOT + 2.36.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 1b9b70b4e..b3813b522 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.35.1-alpha-SNAPSHOT + 2.36.0-alpha grpc-google-cloud-storage-control-v2 GRPC library for google-cloud-storage com.google.cloud google-cloud-storage-parent - 2.35.1-SNAPSHOT + 2.36.0 diff --git a/grpc-google-cloud-storage-v2/pom.xml b/grpc-google-cloud-storage-v2/pom.xml index a8f618376..07b946fef 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.35.1-alpha-SNAPSHOT + 2.36.0-alpha grpc-google-cloud-storage-v2 GRPC library for grpc-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.35.1-SNAPSHOT + 2.36.0 diff --git a/pom.xml b/pom.xml index 98845612a..b442bca53 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-storage-parent pom - 2.35.1-SNAPSHOT + 2.36.0 Storage Parent https://github.com/googleapis/java-storage @@ -76,7 +76,7 @@ com.google.cloud google-cloud-storage - 2.35.1-SNAPSHOT + 2.36.0 com.google.apis @@ -117,32 +117,32 @@ com.google.api.grpc proto-google-cloud-storage-v2 - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha com.google.api.grpc grpc-google-cloud-storage-v2 - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha com.google.api.grpc gapic-google-cloud-storage-v2 - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha com.google.api.grpc grpc-google-cloud-storage-control-v2 - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha com.google.api.grpc proto-google-cloud-storage-control-v2 - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha com.google.cloud google-cloud-storage-control - 2.35.1-alpha-SNAPSHOT + 2.36.0-alpha com.google.cloud diff --git a/proto-google-cloud-storage-control-v2/pom.xml b/proto-google-cloud-storage-control-v2/pom.xml index f028d71dd..9eb168b6e 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.35.1-alpha-SNAPSHOT + 2.36.0-alpha proto-google-cloud-storage-control-v2 Proto library for proto-google-cloud-storage-control-v2 com.google.cloud google-cloud-storage-parent - 2.35.1-SNAPSHOT + 2.36.0 diff --git a/proto-google-cloud-storage-v2/pom.xml b/proto-google-cloud-storage-v2/pom.xml index 6dcaf9449..dab19adc0 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.35.1-alpha-SNAPSHOT + 2.36.0-alpha proto-google-cloud-storage-v2 PROTO library for proto-google-cloud-storage-v2 com.google.cloud google-cloud-storage-parent - 2.35.1-SNAPSHOT + 2.36.0 diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 6211bd424..67c0b685d 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-storage - 2.35.1-SNAPSHOT + 2.36.0 diff --git a/storage-shared-benchmarking/pom.xml b/storage-shared-benchmarking/pom.xml index 5bb630203..5ede2f48a 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.35.1-SNAPSHOT + 2.36.0 @@ -31,7 +31,7 @@ com.google.cloud google-cloud-storage - 2.35.1-SNAPSHOT + 2.36.0 tests diff --git a/versions.txt b/versions.txt index 1ed68144a..41866bb30 100644 --- a/versions.txt +++ b/versions.txt @@ -1,10 +1,10 @@ # Format: # module:released-version:current-version -google-cloud-storage:2.35.0:2.35.1-SNAPSHOT -gapic-google-cloud-storage-v2:2.35.0-alpha:2.35.1-alpha-SNAPSHOT -grpc-google-cloud-storage-v2:2.35.0-alpha:2.35.1-alpha-SNAPSHOT -proto-google-cloud-storage-v2:2.35.0-alpha:2.35.1-alpha-SNAPSHOT -google-cloud-storage-control:2.35.0-alpha:2.35.1-alpha-SNAPSHOT -proto-google-cloud-storage-control-v2:2.35.0-alpha:2.35.1-alpha-SNAPSHOT -grpc-google-cloud-storage-control-v2:2.35.0-alpha:2.35.1-alpha-SNAPSHOT +google-cloud-storage:2.36.0:2.36.0 +gapic-google-cloud-storage-v2:2.36.0-alpha:2.36.0-alpha +grpc-google-cloud-storage-v2:2.36.0-alpha:2.36.0-alpha +proto-google-cloud-storage-v2:2.36.0-alpha:2.36.0-alpha +google-cloud-storage-control:2.36.0-alpha:2.36.0-alpha +proto-google-cloud-storage-control-v2:2.36.0-alpha:2.36.0-alpha +grpc-google-cloud-storage-control-v2:2.36.0-alpha:2.36.0-alpha