diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml
index 3473042c08..f60d774937 100644
--- a/.github/.OwlBot.lock.yaml
+++ b/.github/.OwlBot.lock.yaml
@@ -13,4 +13,5 @@
# limitations under the License.
docker:
image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest
- digest: sha256:df8d7b2cc0dbc65871e7edd86601901a0612b272fa3f7f0eb590c5c53aa5f92e
+ digest: sha256:fc52b202aa298a50a12c64efd04fea3884d867947effe2fa85382a246c09e813
+# created: 2022-04-06T16:30:03.627422514Z
diff --git a/.github/auto-label.yaml b/.github/auto-label.yaml
new file mode 100644
index 0000000000..4caef688b7
--- /dev/null
+++ b/.github/auto-label.yaml
@@ -0,0 +1,15 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+requestsize:
+ enabled: true
diff --git a/.github/sync-repo-settings.yaml b/.github/sync-repo-settings.yaml
index 47afe3b4e7..5de852eebe 100644
--- a/.github/sync-repo-settings.yaml
+++ b/.github/sync-repo-settings.yaml
@@ -91,6 +91,20 @@ branchProtectionRules:
- units (11)
- 'Kokoro - Test: Integration'
- cla/google
+ - pattern: feat/grpc-storage
+ isAdminEnforced: true
+ requiredApprovingReviewCount: 1
+ requiresCodeOwnerReviews: true
+ requiresStrictStatusChecks: false
+ requiredStatusCheckContexts:
+ - dependencies (8)
+ - dependencies (11)
+ - lint
+ - clirr
+ - units (8)
+ - units (11)
+ - 'Kokoro - Test: Integration'
+ - cla/google
permissionRules:
- team: yoshi-admins
permission: admin
diff --git a/.kokoro/presubmit/graalvm-native.cfg b/.kokoro/presubmit/graalvm-native.cfg
index 4c7225ec92..c0d2e84254 100644
--- a/.kokoro/presubmit/graalvm-native.cfg
+++ b/.kokoro/presubmit/graalvm-native.cfg
@@ -31,3 +31,8 @@ env_vars: {
key: "SECRET_MANAGER_KEYS"
value: "java-it-service-account"
}
+
+env_vars: {
+ key: "IT_SERVICE_ACCOUNT_EMAIL"
+ value: "it-service-account@gcloud-devel.iam.gserviceaccount.com"
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9e92957846..15d0a2cfc9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,31 @@
# Changelog
+### [2.6.1](https://github.com/googleapis/java-storage/compare/v2.6.0...v2.6.1) (2022-04-15)
+
+
+### Bug Fixes
+
+* add gccl-invocation-id interceptor ([#1309](https://github.com/googleapis/java-storage/issues/1309)) ([335c267](https://github.com/googleapis/java-storage/commit/335c2679b70f0bcd4db895d9cb4cbe97175e8070))
+* **java:** add service account email to Native Image testing kokoro job ([#1348](https://github.com/googleapis/java-storage/issues/1348)) ([9f76fcc](https://github.com/googleapis/java-storage/commit/9f76fccfddcc0d3a671ec4281dab303da07b9959))
+
+
+### Documentation
+
+* Adding PubSub Notification Samples ([#1317](https://github.com/googleapis/java-storage/issues/1317)) ([fa9920d](https://github.com/googleapis/java-storage/commit/fa9920d9097cfe6863c3e733a091c9b867d603ef))
+* Adding Samples for Creating Dual Region Buckets ([#1341](https://github.com/googleapis/java-storage/issues/1341)) ([9396061](https://github.com/googleapis/java-storage/commit/9396061ac71f98efd6784c34da3bbea04f48873d))
+* Update CreateBucketPubSubNotification to have line without horizontal scrolling ([#1335](https://github.com/googleapis/java-storage/issues/1335)) ([09b7842](https://github.com/googleapis/java-storage/commit/09b78424f7090c7c0469709a357a06143668e31b))
+
+
+### Dependencies
+
+* update dependency com.google.apis:google-api-services-storage to v1-rev20220401-1.32.1 ([#1337](https://github.com/googleapis/java-storage/issues/1337)) ([a5050e2](https://github.com/googleapis/java-storage/commit/a5050e230a620ba727a93c0a93f0bf82a011ce99))
+* update dependency com.google.cloud:google-cloud-pubsub to v1.116.3 ([#1327](https://github.com/googleapis/java-storage/issues/1327)) ([9d8c520](https://github.com/googleapis/java-storage/commit/9d8c520acca7f56f5af46348bc1db71bda1f93aa))
+* update dependency com.google.cloud:google-cloud-shared-dependencies to v2.10.0 ([#1352](https://github.com/googleapis/java-storage/issues/1352)) ([ab46f98](https://github.com/googleapis/java-storage/commit/ab46f985768c1539babf4c14a7e030083776ce0e))
+* update dependency com.google.cloud:native-image-support to v0.12.11 ([#1319](https://github.com/googleapis/java-storage/issues/1319)) ([c338c54](https://github.com/googleapis/java-storage/commit/c338c54210940dbe3b97aa0e7b13904e72ede91d))
+* update dependency com.google.cloud:native-image-support to v0.13.1 ([#1353](https://github.com/googleapis/java-storage/issues/1353)) ([0f76d27](https://github.com/googleapis/java-storage/commit/0f76d2773bc159b1c8a9eeddb54ae8406da86e7a))
+* update kms.version to v0.95.2 ([#1331](https://github.com/googleapis/java-storage/issues/1331)) ([2ca4883](https://github.com/googleapis/java-storage/commit/2ca488362ce2cb2b620ed6dc846d76b095d44a31))
+* update kms.version to v0.95.3 ([#1346](https://github.com/googleapis/java-storage/issues/1346)) ([a4f9503](https://github.com/googleapis/java-storage/commit/a4f95038e56ac36badf68edd072705621fec1dbe))
+
## [2.6.0](https://github.com/googleapis/java-storage/compare/v2.5.1...v2.6.0) (2022-03-30)
diff --git a/README.md b/README.md
index 5f38caabf1..f6208c767b 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
- 25.0.0
+ 25.1.0
pom
import
@@ -41,7 +41,7 @@ If you are using Maven without BOM, add this to your dependencies:
com.google.cloud
google-cloud-storage
- 2.5.1
+ 2.6.0
```
@@ -49,20 +49,20 @@ If you are using Maven without 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:25.0.0')
+implementation platform('com.google.cloud:libraries-bom:25.1.0')
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.5.1'
+implementation 'com.google.cloud:google-cloud-storage:2.6.0'
```
If you are using SBT, add this to your dependencies
```Scala
-libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "2.5.1"
+libraryDependencies += "com.google.cloud" % "google-cloud-storage" % "2.6.0"
```
## Authentication
@@ -240,9 +240,12 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-storage/tree/
| Change Default Storage Class | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/ChangeDefaultStorageClass.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/ChangeDefaultStorageClass.java) |
| Configure Bucket Cors | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/ConfigureBucketCors.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/ConfigureBucketCors.java) |
| Create Bucket | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucket.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucket.java) |
+| Create Bucket Dual Region | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java) |
+| Create Bucket Pub Sub Notification | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java) |
| Create Bucket With Storage Class And Location | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithStorageClassAndLocation.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithStorageClassAndLocation.java) |
| Create Bucket With Turbo Replication | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithTurboReplication.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketWithTurboReplication.java) |
| Delete Bucket | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucket.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucket.java) |
+| Delete Bucket Pub Sub Notification | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucketPubSubNotification.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucketPubSubNotification.java) |
| Disable Bucket Versioning | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/DisableBucketVersioning.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/DisableBucketVersioning.java) |
| Disable Default Event Based Hold | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/DisableDefaultEventBasedHold.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/DisableDefaultEventBasedHold.java) |
| Disable Lifecycle Management | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/DisableLifecycleManagement.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/DisableLifecycleManagement.java) |
@@ -262,10 +265,12 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-storage/tree/
| Get Uniform Bucket Level Access | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/GetUniformBucketLevelAccess.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/GetUniformBucketLevelAccess.java) |
| List Bucket Iam Members | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/ListBucketIamMembers.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/ListBucketIamMembers.java) |
| List Buckets | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/ListBuckets.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/ListBuckets.java) |
+| List Pub Sub Notifications | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/ListPubSubNotifications.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/ListPubSubNotifications.java) |
| Lock Retention Policy | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/LockRetentionPolicy.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/LockRetentionPolicy.java) |
| Make Bucket Public | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/MakeBucketPublic.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/MakeBucketPublic.java) |
| Print Bucket Acl | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/PrintBucketAcl.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/PrintBucketAcl.java) |
| Print Bucket Acl Filter By User | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/PrintBucketAclFilterByUser.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/PrintBucketAclFilterByUser.java) |
+| Print Pub Sub Notification | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/PrintPubSubNotification.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/PrintPubSubNotification.java) |
| Remove Bucket Cors | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketCors.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketCors.java) |
| Remove Bucket Default Kms Key | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketDefaultKmsKey.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketDefaultKmsKey.java) |
| Remove Bucket Default Owner | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketDefaultOwner.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/RemoveBucketDefaultOwner.java) |
diff --git a/gapic-google-cloud-storage-v2/pom.xml b/gapic-google-cloud-storage-v2/pom.xml
index 643306e684..9a9d79f9a2 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.6.0-alpha
+ 2.6.1-alpha
gapic-google-cloud-storage-v2
GRPC library for gapic-google-cloud-storage-v2
com.google.cloud
google-cloud-storage-parent
- 2.6.0
+ 2.6.1
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 7844e020f0..093223d5ac 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
@@ -891,6 +891,7 @@ public final Policy setIamPolicy(String resource, Policy policy) {
* CryptoKeyName.of("[PROJECT]", "[LOCATION]", "[KEY_RING]", "[CRYPTO_KEY]")
* .toString())
* .setPolicy(Policy.newBuilder().build())
+ * .setUpdateMask(FieldMask.newBuilder().build())
* .build();
* Policy response = storageClient.setIamPolicy(request);
* }
@@ -917,6 +918,7 @@ public final Policy setIamPolicy(SetIamPolicyRequest request) {
* CryptoKeyName.of("[PROJECT]", "[LOCATION]", "[KEY_RING]", "[CRYPTO_KEY]")
* .toString())
* .setPolicy(Policy.newBuilder().build())
+ * .setUpdateMask(FieldMask.newBuilder().build())
* .build();
* ApiFuture future = storageClient.setIamPolicyCallable().futureCall(request);
* // Do something.
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 2fc3b0b438..eeff896f37 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
@@ -35,6 +35,7 @@
import com.google.api.gax.rpc.StatusCode;
import com.google.api.resourcenames.ResourceName;
import com.google.common.collect.Lists;
+import com.google.iam.v1.AuditConfig;
import com.google.iam.v1.Binding;
import com.google.iam.v1.GetIamPolicyRequest;
import com.google.iam.v1.Policy;
@@ -654,6 +655,7 @@ public void getIamPolicyTest() throws Exception {
Policy.newBuilder()
.setVersion(351608024)
.addAllBindings(new ArrayList())
+ .addAllAuditConfigs(new ArrayList())
.setEtag(ByteString.EMPTY)
.build();
mockStorage.addResponse(expectedResponse);
@@ -696,6 +698,7 @@ public void getIamPolicyTest2() throws Exception {
Policy.newBuilder()
.setVersion(351608024)
.addAllBindings(new ArrayList())
+ .addAllAuditConfigs(new ArrayList())
.setEtag(ByteString.EMPTY)
.build();
mockStorage.addResponse(expectedResponse);
@@ -736,6 +739,7 @@ public void setIamPolicyTest() throws Exception {
Policy.newBuilder()
.setVersion(351608024)
.addAllBindings(new ArrayList())
+ .addAllAuditConfigs(new ArrayList())
.setEtag(ByteString.EMPTY)
.build();
mockStorage.addResponse(expectedResponse);
@@ -781,6 +785,7 @@ public void setIamPolicyTest2() throws Exception {
Policy.newBuilder()
.setVersion(351608024)
.addAllBindings(new ArrayList())
+ .addAllAuditConfigs(new ArrayList())
.setEtag(ByteString.EMPTY)
.build();
mockStorage.addResponse(expectedResponse);
diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml
index 8374be3fc9..84fba3dc32 100644
--- a/google-cloud-storage/clirr-ignored-differences.xml
+++ b/google-cloud-storage/clirr-ignored-differences.xml
@@ -1,39 +1,4 @@
-
- com/google/cloud/storage/BucketInfo$Builder
- com.google.cloud.storage.BucketInfo$Builder setRpo(com.google.cloud.storage.Rpo)
- 7013
-
-
- com/google/cloud/storage/BucketInfo$LifecycleRule$LifecycleAction
- BucketInfo$LifecycleRule$LifecycleAction()
- 7004
-
-
- com/google/cloud/storage/Storage
- *.Notification createNotification(*.String, *.NotificationInfo)
- 7012
-
-
- com/google/cloud/storage/Storage
- *.Notification getNotification(*.String, *.String)
- 7012
-
-
- com/google/cloud/storage/Storage
- java.util.List listNotifications(*.String)
- 7012
-
-
- com/google/cloud/storage/Storage
- boolean deleteNotification(*.String, *.String)
- 7012
-
-
- com/google/cloud/storage/spi/v1/StorageRpc
- *.model.Notification getNotification(*.String, *.String)
- 7012
-
diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml
index ffb2bff960..1c2f4df351 100644
--- a/google-cloud-storage/pom.xml
+++ b/google-cloud-storage/pom.xml
@@ -2,7 +2,7 @@
4.0.0
google-cloud-storage
- 2.6.0
+ 2.6.1
jar
Google Cloud Storage
https://github.com/googleapis/java-storage
@@ -12,11 +12,11 @@
com.google.cloud
google-cloud-storage-parent
- 2.6.0
+ 2.6.1
google-cloud-storage
- 0.95.1
+ 0.95.3
@@ -92,6 +92,10 @@
com.fasterxml.jackson.core
jackson-core
+
+ com.google.code.findbugs
+ jsr305
+
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 5e06b6ce24..e03110ff2c 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
@@ -1224,7 +1224,7 @@ public abstract static class Builder {
/**
* Sets the bucket's location. Data for blobs in the bucket resides in physical storage within
- * this region. A list of supported values is available here.
*/
public abstract Builder setLocation(String location);
@@ -1731,7 +1731,7 @@ public Long getMetageneration() {
/**
* Returns the bucket's location. Data for blobs in the bucket resides in physical storage within
- * this region.
+ * this region or regions.
*
* @see Bucket Locations
*/
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Retrying.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Retrying.java
index 3daf2c17ec..51ce17bf3f 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Retrying.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Retrying.java
@@ -22,6 +22,7 @@
import com.google.api.gax.retrying.ResultRetryAlgorithm;
import com.google.api.gax.retrying.RetrySettings;
import com.google.cloud.RetryHelper.RetryHelperException;
+import com.google.cloud.storage.spi.v1.HttpRpcContext;
import java.util.concurrent.Callable;
import java.util.function.Function;
@@ -47,11 +48,15 @@ final class Retrying {
*/
static U run(
StorageOptions options, ResultRetryAlgorithm> algorithm, Callable c, Function f) {
+ HttpRpcContext httpRpcContext = HttpRpcContext.getInstance();
try {
+ httpRpcContext.newInvocationId();
T result = runWithRetries(c, options.getRetrySettings(), algorithm, options.getClock());
return result == null ? null : f.apply(result);
} catch (RetryHelperException e) {
throw StorageException.coalesce(e);
+ } finally {
+ httpRpcContext.clearInvocationId();
}
}
}
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 f3de842fbd..d2bfa27607 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
@@ -38,8 +38,9 @@ public class StorageOptions extends ServiceOptions {
private static final String GCS_SCOPE = "https://www.googleapis.com/auth/devstorage.full_control";
private static final Set SCOPES = ImmutableSet.of(GCS_SCOPE);
private static final String DEFAULT_HOST = "https://storage.googleapis.com";
-
+ private static final boolean DEFAULT_INCLUDE_INVOCATION_ID = true;
private final RetryAlgorithmManager retryAlgorithmManager;
+ private final boolean includeInvocationId;
public static class DefaultStorageFactory implements StorageFactory {
@@ -64,11 +65,13 @@ public ServiceRpc create(StorageOptions options) {
public static class Builder extends ServiceOptions.Builder {
private StorageRetryStrategy storageRetryStrategy;
+ private boolean includeInvocationId;
private Builder() {}
private Builder(StorageOptions options) {
super(options);
+ this.includeInvocationId = options.includeInvocationId;
}
@Override
@@ -93,6 +96,17 @@ public Builder setStorageRetryStrategy(StorageRetryStrategy storageRetryStrategy
return this;
}
+ /**
+ * Override default enablement of invocation id added to x-goog-api-client header.
+ *
+ * @param includeInvocationId a boolean to change enablement of invocation id
+ * @return the builder
+ */
+ Builder setIncludeInvocationId(boolean includeInvocationId) {
+ this.includeInvocationId = includeInvocationId;
+ return this;
+ }
+
@Override
public StorageOptions build() {
return new StorageOptions(this, new StorageDefaults());
@@ -105,6 +119,7 @@ private StorageOptions(Builder builder, StorageDefaults serviceDefaults) {
new RetryAlgorithmManager(
MoreObjects.firstNonNull(
builder.storageRetryStrategy, serviceDefaults.getStorageRetryStrategy()));
+ this.includeInvocationId = builder.includeInvocationId;
}
private static class StorageDefaults implements ServiceDefaults {
@@ -127,6 +142,10 @@ public TransportOptions getDefaultTransportOptions() {
public StorageRetryStrategy getStorageRetryStrategy() {
return StorageRetryStrategy.getDefaultStorageRetryStrategy();
}
+
+ boolean isIncludeInvocationId() {
+ return DEFAULT_INCLUDE_INVOCATION_ID;
+ }
}
public static HttpTransportOptions getDefaultHttpTransportOptions() {
@@ -153,6 +172,11 @@ RetryAlgorithmManager getRetryAlgorithmManager() {
return retryAlgorithmManager;
}
+ /** Returns if Invocation ID is enabled and transmitted through x-goog-api-client header. */
+ boolean isIncludeInvocationId() {
+ return includeInvocationId;
+ }
+
/** Returns a default {@code StorageOptions} instance. */
public static StorageOptions getDefaultInstance() {
return newBuilder().build();
@@ -180,6 +204,8 @@ public boolean equals(Object obj) {
}
public static Builder newBuilder() {
- return new Builder().setHost(DEFAULT_HOST);
+ return new Builder()
+ .setHost(DEFAULT_HOST)
+ .setIncludeInvocationId(DEFAULT_INCLUDE_INVOCATION_ID);
}
}
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpRpcContext.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpRpcContext.java
new file mode 100644
index 0000000000..a62e7f99d4
--- /dev/null
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpRpcContext.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.storage.spi.v1;
+
+import com.google.api.core.InternalApi;
+import java.util.UUID;
+import java.util.function.Supplier;
+import javax.annotation.Nullable;
+
+@InternalApi
+public final class HttpRpcContext {
+
+ private static final Object GET_INSTANCE_LOCK = new Object();
+
+ private static volatile HttpRpcContext instance;
+
+ private final ThreadLocal invocationId;
+ private final Supplier supplier;
+
+ HttpRpcContext(Supplier randomUUID) {
+ this.invocationId = new InheritableThreadLocal<>();
+ this.supplier = randomUUID;
+ }
+
+ @InternalApi
+ @Nullable
+ public UUID getInvocationId() {
+ return invocationId.get();
+ }
+
+ @InternalApi
+ public UUID newInvocationId() {
+ invocationId.set(supplier.get());
+ return getInvocationId();
+ }
+
+ @InternalApi
+ public void clearInvocationId() {
+ invocationId.remove();
+ }
+
+ @InternalApi
+ public static HttpRpcContext init() {
+ return new HttpRpcContext(UUID::randomUUID);
+ }
+
+ @InternalApi
+ public static HttpRpcContext getInstance() {
+ if (instance == null) {
+ synchronized (GET_INSTANCE_LOCK) {
+ if (instance == null) {
+ instance = init();
+ }
+ }
+ }
+ return instance;
+ }
+}
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 d0c1ff8a96..70f3493295 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
@@ -18,6 +18,7 @@
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import com.google.api.client.googleapis.batch.BatchRequest;
@@ -26,6 +27,7 @@
import com.google.api.client.http.ByteArrayContent;
import com.google.api.client.http.EmptyContent;
import com.google.api.client.http.GenericUrl;
+import com.google.api.client.http.HttpExecuteInterceptor;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
@@ -86,6 +88,8 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.UUID;
+import javax.annotation.Nullable;
public class HttpStorageRpc implements StorageRpc {
public static final String DEFAULT_PROJECTION = "full";
@@ -114,6 +118,7 @@ public HttpStorageRpc(StorageOptions options) {
// Open Census initialization
censusHttpModule = new CensusHttpModule(tracer, true);
initializer = censusHttpModule.getHttpRequestInitializer(initializer);
+ initializer = new InvocationIdInitializer(initializer);
batchRequestInitializer = censusHttpModule.getHttpRequestInitializer(null);
storage =
new Storage.Builder(transport, new JacksonFactory(), initializer)
@@ -122,6 +127,54 @@ public HttpStorageRpc(StorageOptions options) {
.build();
}
+ private static final class InvocationIdInitializer implements HttpRequestInitializer {
+ @Nullable HttpRequestInitializer initializer;
+
+ private InvocationIdInitializer(@Nullable HttpRequestInitializer initializer) {
+ this.initializer = initializer;
+ }
+
+ @Override
+ public void initialize(HttpRequest request) throws IOException {
+ checkNotNull(request);
+ if (this.initializer != null) {
+ this.initializer.initialize(request);
+ }
+ request.setInterceptor(new InvocationIdInterceptor(request.getInterceptor()));
+ }
+ }
+
+ private static final class InvocationIdInterceptor implements HttpExecuteInterceptor {
+ @Nullable HttpExecuteInterceptor interceptor;
+
+ private InvocationIdInterceptor(@Nullable HttpExecuteInterceptor interceptor) {
+ this.interceptor = interceptor;
+ }
+
+ @Override
+ public void intercept(HttpRequest request) throws IOException {
+ checkNotNull(request);
+ if (this.interceptor != null) {
+ this.interceptor.intercept(request);
+ }
+ UUID invocationId = HttpRpcContext.getInstance().getInvocationId();
+ final String signatureKey = "Signature="; // For V2 and V4 signedURLs
+ final String builtURL = request.getUrl().build();
+ if (invocationId != null && !builtURL.contains(signatureKey)) {
+ HttpHeaders headers = request.getHeaders();
+ String existing = (String) headers.get("x-goog-api-client");
+ String invocationEntry = "gccl-invocation-id/" + invocationId;
+ final String newValue;
+ if (existing != null && !existing.isEmpty()) {
+ newValue = existing + " " + invocationEntry;
+ } else {
+ newValue = invocationEntry;
+ }
+ headers.set("x-goog-api-client", newValue);
+ }
+ }
+ }
+
private class DefaultRpcBatch implements RpcBatch {
// Batch size is limited as, due to some current service implementation details, the service
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageOptionsTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageOptionsTest.java
index 5c9c708c10..ac478ab345 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageOptionsTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageOptionsTest.java
@@ -17,10 +17,18 @@
package com.google.cloud.storage;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import com.google.api.client.testing.http.MockLowLevelHttpResponse;
import com.google.cloud.TransportOptions;
+import com.google.cloud.Tuple;
+import com.google.cloud.http.HttpTransportOptions;
+import com.google.cloud.storage.spi.v1.AuditingHttpTransport;
+import java.util.Optional;
import org.easymock.EasyMock;
import org.junit.Assert;
+import org.junit.Ignore;
import org.junit.Test;
public class StorageOptionsTest {
@@ -65,4 +73,54 @@ public void testDefaultInstanceSpecifiesCorrectHost() {
assertThat(opts1.getHost()).isEqualTo("https://storage.googleapis.com");
}
+
+ @Test
+ public void testDefaultInvocationId() {
+ StorageOptions opts1 = StorageOptions.getDefaultInstance();
+
+ assertTrue(opts1.isIncludeInvocationId());
+ }
+
+ @Test
+ public void testDisableInvocationId() {
+ StorageOptions opts1 = StorageOptions.newBuilder().setIncludeInvocationId(false).build();
+
+ assertFalse(opts1.isIncludeInvocationId());
+ }
+
+ /**
+ * Disabled until {@link StorageOptions#isIncludeInvocationId()} and {@link
+ * StorageOptions.Builder#setIncludeInvocationId(boolean)} are public.
+ */
+ @Test
+ @Ignore
+ public void testInvocationIdIsNotPassedThroughWhenDisabled() {
+ MockLowLevelHttpResponse response =
+ new MockLowLevelHttpResponse()
+ .setContentType("application/json")
+ .setContent(
+ "{\n"
+ + " \"kind\": \"storage#serviceAccount\",\n"
+ + " \"email_address\": \"service-234234@gs-project-accounts.iam.gserviceaccount.com\"\n"
+ + "}\n")
+ .setStatusCode(200);
+ AuditingHttpTransport transport = new AuditingHttpTransport(response);
+ TransportOptions transportOptions =
+ HttpTransportOptions.newBuilder().setHttpTransportFactory(() -> transport).build();
+ Storage service =
+ StorageOptions.getDefaultInstance()
+ .toBuilder()
+ .setTransportOptions(transportOptions)
+ .setIncludeInvocationId(false)
+ .build()
+ .getService();
+ service.getServiceAccount("test-project");
+ Optional> anyXGoogApiClientWithGcclInvocationId =
+ transport.getAddHeaderCalls().stream()
+ .filter(t -> "x-goog-api-client".equals(t.x()) && t.y().contains("gccl-invocation-id/"))
+ .findFirst();
+
+ assertFalse(anyXGoogApiClientWithGcclInvocationId.isPresent());
+ assertThat(transport.getBuildRequestCalls()).hasSize(1);
+ }
}
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
index 80d1ebc384..d755d38d2a 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
@@ -3560,6 +3560,16 @@ public void testBucketLocationType() throws ExecutionException, InterruptedExcep
RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS);
}
+ @Test
+ public void testBucketLocationDualRegion() {
+ String bucketName = RemoteStorageHelper.generateBucketName();
+ String dualRegionLocation = "US-EAST1+US-WEST1";
+ Bucket bucket =
+ storage.create(BucketInfo.newBuilder(bucketName).setLocation(dualRegionLocation).build());
+ assertEquals(bucket.getLocation(), dualRegionLocation);
+ assertEquals(bucket.getLocationType(), "dual-region");
+ }
+
@Test
public void testBucketLogging() throws ExecutionException, InterruptedException {
String logsBucket = RemoteStorageHelper.generateBucketName();
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/AuditingHttpTransport.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/AuditingHttpTransport.java
new file mode 100644
index 0000000000..edb7d64c14
--- /dev/null
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/AuditingHttpTransport.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.storage.spi.v1;
+
+import com.google.api.client.http.HttpTransport;
+import com.google.api.client.http.LowLevelHttpRequest;
+import com.google.api.client.http.LowLevelHttpResponse;
+import com.google.cloud.Tuple;
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public final class AuditingHttpTransport extends HttpTransport {
+ private final LowLevelHttpResponse response;
+ private final List> buildRequestCalls;
+ private final List> addHeaderCalls;
+
+ public AuditingHttpTransport(LowLevelHttpResponse response) {
+ this.response = response;
+ this.buildRequestCalls = Collections.synchronizedList(new ArrayList<>());
+ this.addHeaderCalls = Collections.synchronizedList(new ArrayList<>());
+ }
+
+ public List> getBuildRequestCalls() {
+ return ImmutableList.copyOf(buildRequestCalls);
+ }
+
+ public List> getAddHeaderCalls() {
+ return ImmutableList.copyOf(addHeaderCalls);
+ }
+
+ @Override
+ protected LowLevelHttpRequest buildRequest(String method, String url) {
+ buildRequestCalls.add(Tuple.of(method, url));
+ return new LowLevelHttpRequest() {
+ @Override
+ public void addHeader(String name, String value) {
+ addHeaderCalls.add(Tuple.of(name, value));
+ }
+
+ @Override
+ public LowLevelHttpResponse execute() {
+ return response;
+ }
+ };
+ }
+}
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/HttpRpcContextTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/HttpRpcContextTest.java
new file mode 100644
index 0000000000..3e8b295bda
--- /dev/null
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/spi/v1/HttpRpcContextTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.storage.spi.v1;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.api.client.testing.http.MockLowLevelHttpResponse;
+import com.google.cloud.TransportOptions;
+import com.google.cloud.Tuple;
+import com.google.cloud.WriteChannel;
+import com.google.cloud.http.HttpTransportOptions;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.Optional;
+import java.util.UUID;
+import org.junit.Test;
+
+public class HttpRpcContextTest {
+ @Test
+ public void testNewInvocationId() {
+ UUID uuid = UUID.fromString("28220dff-1e8b-4770-9e10-022c2a99d8f3");
+ HttpRpcContext testContext = new HttpRpcContext(() -> uuid);
+
+ assertThat(testContext.newInvocationId()).isEqualTo(uuid);
+ assertThat(testContext.getInvocationId()).isEqualTo(uuid);
+ // call again to ensure the id is consistent with our supplier
+ assertThat(testContext.newInvocationId()).isEqualTo(uuid);
+ assertThat(testContext.getInvocationId()).isEqualTo(uuid);
+ }
+
+ @Test
+ public void testInvocationIdIsPassedThrough() {
+ MockLowLevelHttpResponse response =
+ new MockLowLevelHttpResponse()
+ .setContentType("application/json")
+ .setContent(
+ "{\n"
+ + " \"kind\": \"storage#serviceAccount\",\n"
+ + " \"email_address\": \"service-234234@gs-project-accounts.iam.gserviceaccount.com\"\n"
+ + "}\n")
+ .setStatusCode(200);
+ AuditingHttpTransport transport = new AuditingHttpTransport(response);
+ TransportOptions transportOptions =
+ HttpTransportOptions.newBuilder().setHttpTransportFactory(() -> transport).build();
+ Storage service =
+ StorageOptions.getDefaultInstance()
+ .toBuilder()
+ .setTransportOptions(transportOptions)
+ .build()
+ .getService();
+ service.getServiceAccount("test-project");
+ Optional> anyXGoogApiClientWithGcclInvocationId =
+ transport.getAddHeaderCalls().stream()
+ .filter(t -> "x-goog-api-client".equals(t.x()) && t.y().contains("gccl-invocation-id/"))
+ .findFirst();
+ assertTrue(anyXGoogApiClientWithGcclInvocationId.isPresent());
+ assertThat(transport.getBuildRequestCalls()).hasSize(1);
+ }
+
+ @Test
+ public void testInvocationIdNotInSignedURL_v2() throws IOException {
+ URL signedUrlV2 =
+ new URL(
+ "http://www.test.com/test-bucket/test1.txt?GoogleAccessId=testClient-test@test.com&Expires=1553839761&Signature=MJUBXAZ7");
+ doTestInvocationIdNotInSignedURL(signedUrlV2);
+ }
+
+ @Test
+ public void testInvocationIdNotInSignedURL_v4() throws IOException {
+ URL signedUrlV4 =
+ new URL(
+ "http://www.test.com/test-bucket/test1.txt?X-Goog-Algorithm=&X-Goog-Credential=&X-Goog-Date=&X-Goog-Expires=&X-Goog-SignedHeaders=&X-Goog-Signature=MJUBXAZ7");
+ doTestInvocationIdNotInSignedURL(signedUrlV4);
+ }
+
+ private void doTestInvocationIdNotInSignedURL(URL signedUrl) throws IOException {
+ MockLowLevelHttpResponse response =
+ new MockLowLevelHttpResponse()
+ .setContentType("text/plain")
+ .setHeaderNames(ImmutableList.of("Location"))
+ .setHeaderValues(ImmutableList.of("http://test"))
+ .setStatusCode(201);
+ AuditingHttpTransport transport = new AuditingHttpTransport(response);
+ TransportOptions transportOptions =
+ HttpTransportOptions.newBuilder().setHttpTransportFactory(() -> transport).build();
+ Storage service =
+ StorageOptions.getDefaultInstance()
+ .toBuilder()
+ .setTransportOptions(transportOptions)
+ .build()
+ .getService();
+ WriteChannel writer = service.writer(signedUrl);
+ writer.write(ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8)));
+ Optional> anyXGoogApiClientWithGcclInvocationId =
+ transport.getAddHeaderCalls().stream()
+ .filter(t -> "x-goog-api-client".equals(t.x()) && t.y().contains("gccl-invocation-id/"))
+ .findFirst();
+ assertFalse(anyXGoogApiClientWithGcclInvocationId.isPresent());
+ assertThat(transport.getBuildRequestCalls()).hasSize(1);
+ }
+}
diff --git a/grpc-google-cloud-storage-v2/pom.xml b/grpc-google-cloud-storage-v2/pom.xml
index 4516cf7add..27a037d1ad 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.6.0-alpha
+ 2.6.1-alpha
grpc-google-cloud-storage-v2
GRPC library for grpc-google-cloud-storage-v2
com.google.cloud
google-cloud-storage-parent
- 2.6.0
+ 2.6.1
diff --git a/owlbot.py b/owlbot.py
index 2b33b683f4..c94718a388 100644
--- a/owlbot.py
+++ b/owlbot.py
@@ -33,5 +33,6 @@
'.kokoro/nightly/samples.cfg',
'.kokoro/presubmit/integration.cfg',
'.kokoro/presubmit/samples.cfg',
+ '.kokoro/presubmit/graalvm-native.cfg',
'CONTRIBUTING.md'
])
diff --git a/pom.xml b/pom.xml
index 5daef9d926..b9823efc72 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.google.cloud
google-cloud-storage-parent
pom
- 2.6.0
+ 2.6.1
Storage Parent
https://github.com/googleapis/java-storage
@@ -54,7 +54,7 @@
UTF-8
github
google-cloud-storage-parent
- 2.9.0
+ 2.10.0
@@ -70,17 +70,17 @@
com.google.cloud
google-cloud-storage
- 2.6.0
+ 2.6.1
com.google.apis
google-api-services-storage
- v1-rev20220210-1.32.1
+ v1-rev20220401-1.32.1
com.google.cloud
google-cloud-pubsub
- 1.116.2
+ 1.116.3
test
@@ -111,22 +111,22 @@
com.google.api.grpc
proto-google-cloud-storage-v2
- 2.6.0-alpha
+ 2.6.1-alpha
com.google.api.grpc
grpc-google-cloud-storage-v2
- 2.6.0-alpha
+ 2.6.1-alpha
com.google.api.grpc
gapic-google-cloud-storage-v2
- 2.6.0-alpha
+ 2.6.1-alpha
com.google.cloud
google-cloud-conformance-tests
- 0.2.9
+ 0.2.10
test
diff --git a/proto-google-cloud-storage-v2/clirr-ignored-differences.xml b/proto-google-cloud-storage-v2/clirr-ignored-differences.xml
index 2fafe5526e..fc73daacd1 100644
--- a/proto-google-cloud-storage-v2/clirr-ignored-differences.xml
+++ b/proto-google-cloud-storage-v2/clirr-ignored-differences.xml
@@ -1,164 +1,4 @@
-
- 7012
- com/google/storage/v2/*OrBuilder
- * get*(*)
-
-
- 7012
- com/google/storage/v2/*OrBuilder
- boolean contains*(*)
-
-
- 7012
- com/google/storage/v2/*OrBuilder
- boolean has*(*)
-
-
-
-
- 6011
- com/google/storage/v2/*
- ZONE_AFFINITY_FIELD_NUMBER
-
-
- 7002
- com/google/storage/v2/*
- * *ZoneAffinity*(*)
-
-
-
-
-
-
- 7005
- com/google/storage/v2/Object*
- * *CustomerEncryption*(*)
- *
-
-
-
- 7006
- com/google/storage/v2/Object*
- * *CustomerEncryption*(*)
- *
-
-
-
- 8001
- com/google/storage/v2/Object$CustomerEncryption*
-
-
-
-
-
- 6011
- com/google/storage/v2/*
- CUSTOM_PLACEMENT_CONFIG_FIELD_NUMBER
-
-
-
- 7002
- com/google/storage/v2/*
- * *CustomPlacementConfig*(*)
-
-
- 7002
- com/google/storage/v2/*
- * *DestinationPredefinedAclValue*(*)
-
-
- 7002
- com/google/storage/v2/*
- * *PredefinedAclValue*(*)
-
-
- 7002
- com/google/storage/v2/*
- * *PredefinedDefaultObjectAclValue*(*)
-
-
- 7002
- com/google/storage/v2/*
- * *PublicAccessPrevention*(*)
-
-
-
- 7005
- com/google/storage/v2/Bucket$IamConfig$Builder
- com.google.storage.v2.Bucket$IamConfig$Builder setPublicAccessPrevention(com.google.storage.v2.Bucket$IamConfig$PublicAccessPrevention)
- com.google.storage.v2.Bucket$IamConfig$Builder setPublicAccessPrevention(java.lang.String)
-
-
-
-
-
- 7005
- com/google/storage/v2/*
- * *(*)
- * *(*)
-
-
-
-
- 7006
- com/google/storage/v2/*
- * *DestinationPredefinedAcl*(*)
- *
-
-
- 7006
- com/google/storage/v2/*
- * *PredefinedAcl*(*)
- *
-
-
- 7006
- com/google/storage/v2/*
- * *PredefinedDefaultObjectAcl*(*)
- *
-
-
- 7006
- com/google/storage/v2/*
- * *PublicAccessPrevention*(*)
- *
-
-
-
- 8001
- com/google/storage/v2/Bucket$CustomPlacementConfig*
-
-
- 8001
- com/google/storage/v2/Bucket$IamConfig$PublicAccessPrevention*
-
-
- 8001
- com/google/storage/v2/PredefinedBucketAcl
-
-
- 8001
- com/google/storage/v2/PredefinedObjectAcl
-
-
diff --git a/proto-google-cloud-storage-v2/pom.xml b/proto-google-cloud-storage-v2/pom.xml
index 7fd3675edb..49fe243350 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.6.0-alpha
+ 2.6.1-alpha
proto-google-cloud-storage-v2
PROTO library for proto-google-cloud-storage-v2
com.google.cloud
google-cloud-storage-parent
- 2.6.0
+ 2.6.1
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 16815493c4..add9193868 100644
--- a/samples/install-without-bom/pom.xml
+++ b/samples/install-without-bom/pom.xml
@@ -15,6 +15,7 @@
com.google.cloud.samples
shared-configuration
1.2.0
+
@@ -29,7 +30,7 @@
com.google.cloud
google-cloud-storage
- 2.5.1
+ 2.6.0
@@ -57,6 +58,12 @@
4.5.13
test
+
+ com.google.cloud
+ google-cloud-pubsub
+ 1.116.3
+ test
+
diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml
index 8d98f37e14..711438da3a 100644
--- a/samples/native-image-sample/pom.xml
+++ b/samples/native-image-sample/pom.xml
@@ -14,6 +14,7 @@
com.google.cloud.samples
shared-configuration
1.2.0
+
@@ -28,7 +29,7 @@
com.google.cloud
libraries-bom
- 25.0.0
+ 25.1.0
pom
import
@@ -57,6 +58,12 @@
1.1.3
test
+
+ com.google.cloud
+ google-cloud-pubsub
+ 1.116.3
+ test
+
@@ -107,7 +114,7 @@
com.google.cloud
native-image-support
- 0.12.10
+ 0.13.1
org.junit.vintage
@@ -170,4 +177,4 @@
-
\ No newline at end of file
+
diff --git a/samples/pom.xml b/samples/pom.xml
index 2c01e6fca0..8de92bd400 100644
--- a/samples/pom.xml
+++ b/samples/pom.xml
@@ -19,6 +19,7 @@
com.google.cloud.samples
shared-configuration
1.2.0
+
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index 6cd97d6cc0..e7bab3f8df 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -15,6 +15,7 @@
com.google.cloud.samples
shared-configuration
1.2.0
+
@@ -27,7 +28,7 @@
com.google.cloud
google-cloud-storage
- 2.6.0
+ 2.6.1
@@ -48,6 +49,12 @@
4.5.13
test
+
+ com.google.cloud
+ google-cloud-pubsub
+ 1.116.3
+ test
+
@@ -84,4 +91,4 @@
-
\ No newline at end of file
+
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 292403d526..01df9ad79e 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -15,6 +15,7 @@
com.google.cloud.samples
shared-configuration
1.2.0
+
@@ -30,7 +31,7 @@
com.google.cloud
libraries-bom
- 25.0.0
+ 25.1.0
pom
import
@@ -56,5 +57,23 @@
1.1.3
test
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.13
+ test
+
+
+ org.apache.httpcomponents
+ httpmime
+ 4.5.13
+ test
+
+
+ com.google.cloud
+ google-cloud-pubsub
+ 1.116.3
+ test
+
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java b/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java
new file mode 100644
index 0000000000..e5a3fccb0d
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketDualRegion.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.storage.bucket;
+
+// [START storage_create_bucket_dual_region]
+
+import com.google.cloud.storage.Bucket;
+import com.google.cloud.storage.BucketInfo;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+
+public class CreateBucketDualRegion {
+
+ public static void createBucketDualRegion(
+ String projectId, String bucketName, String firstRegion, String secondRegion) {
+ // The ID of your GCP project
+ // String projectId = "your-project-id";
+
+ // The ID to give your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ // One of the regions the dual region bucket is to be created in.
+ // String firstRegion = "US-EAST1";
+
+ // The second region the dual region bucket is to be created in.
+ // String secondRegion = "US-WEST1";
+
+ // Construct the dual region ie. "US-EAST1+US-WEST1"
+ String dualRegion = firstRegion + "+" + secondRegion;
+
+ Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
+
+ Bucket bucket =
+ storage.create(BucketInfo.newBuilder(bucketName).setLocation(dualRegion).build());
+
+ System.out.println(
+ "Created bucket " + bucket.getName() + " in location " + bucket.getLocation());
+ }
+}
+// [END storage_create_bucket_dual_region]
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java b/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java
new file mode 100644
index 0000000000..da2b3b3d13
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/CreateBucketPubSubNotification.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.storage.bucket;
+
+// [START storage_create_bucket_notifications]
+import com.google.cloud.storage.Notification;
+import com.google.cloud.storage.NotificationInfo;
+import com.google.cloud.storage.NotificationInfo.EventType;
+import com.google.cloud.storage.NotificationInfo.PayloadFormat;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+import java.util.Map;
+
+public class CreateBucketPubSubNotification {
+
+ public static void createBucketPubSubNotification(
+ String bucketName,
+ String topicName,
+ Map customAttributes,
+ EventType[] eventTypes,
+ String objectNamePrefix,
+ PayloadFormat payloadFormat) {
+ // The ID to give your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ // The name of the topic you would like to create a notification for
+ // String topicName = "projects/{your-project}/topics/{your-topic}";
+
+ // Any custom attributes
+ // Map customAttributes = Map.of("label", "value");
+
+ // The object name prefix for which this notification configuration applies
+ // String objectNamePrefix = "blob-";
+
+ // Desired content of the Payload
+ // PayloadFormat payloadFormat = PayloadFormat.JSON_API_V1.JSON_API_V1;
+
+ Storage storage = StorageOptions.newBuilder().build().getService();
+ NotificationInfo notificationInfo =
+ NotificationInfo.newBuilder(topicName)
+ .setCustomAttributes(customAttributes)
+ .setEventTypes(eventTypes)
+ .setObjectNamePrefix(objectNamePrefix)
+ .setPayloadFormat(payloadFormat)
+ .build();
+ Notification notification = storage.createNotification(bucketName, notificationInfo);
+ String topic = notification.getTopic();
+ System.out.println("Successfully created notification for topic " + topic);
+ }
+}
+// [END storage_create_bucket_notifications]
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucketPubSubNotification.java b/samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucketPubSubNotification.java
new file mode 100644
index 0000000000..dd59e2e189
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/DeleteBucketPubSubNotification.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.storage.bucket;
+
+// [START storage_delete_bucket_notification]
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+
+public class DeleteBucketPubSubNotification {
+
+ public static void deleteBucketPubSubNotification(String bucketName, String notificationId) {
+ // The ID to give your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ // The NotificationId for the notification you would like to delete
+ // String notificationId = "your-unique-notification-id"
+
+ Storage storage = StorageOptions.newBuilder().build().getService();
+ boolean success = storage.deleteNotification(bucketName, notificationId);
+ if (success) {
+ System.out.println("Successfully deleted notification");
+ } else {
+ System.out.println("Failed to find notification");
+ }
+ }
+}
+// [END storage_delete_bucket_notification]
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/ListPubSubNotifications.java b/samples/snippets/src/main/java/com/example/storage/bucket/ListPubSubNotifications.java
new file mode 100644
index 0000000000..b3fb614f8b
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/ListPubSubNotifications.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.storage.bucket;
+
+// [START storage_list_bucket_notifications]
+import com.google.cloud.storage.Notification;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+import java.util.List;
+
+public class ListPubSubNotifications {
+
+ public static void listPubSubNotifications(String bucketName) {
+ // The ID to give your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ Storage storage = StorageOptions.newBuilder().build().getService();
+ List notificationList = storage.listNotifications(bucketName);
+ for (Notification notification : notificationList) {
+ System.out.println(
+ "Found notification " + notification.getTopic() + " for bucket " + bucketName);
+ }
+ }
+}
+// [END storage_list_bucket_notifications]
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/PrintPubSubNotification.java b/samples/snippets/src/main/java/com/example/storage/bucket/PrintPubSubNotification.java
new file mode 100644
index 0000000000..083a0b551a
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/PrintPubSubNotification.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.storage.bucket;
+
+// [START storage_print_pubsub_bucket_notification]
+import com.google.cloud.storage.Notification;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+
+public class PrintPubSubNotification {
+
+ public static void printPubSubNotification(String bucketName, String notificationId) {
+ // The ID to give your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ // The Pub/Sub topic you would like to find
+ // String notificationId = "your-unique-notification-id"
+
+ Storage storage = StorageOptions.newBuilder().build().getService();
+ Notification notification = storage.getNotification(bucketName, notificationId);
+ System.out.println(
+ "Found notification " + notification.getTopic() + " for bucket " + bucketName);
+ }
+}
+// [END storage_print_pubsub_bucket_notification]
diff --git a/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java b/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java
index 822c3189c9..6d434e30ed 100644
--- a/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java
+++ b/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java
@@ -81,12 +81,9 @@
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageRoles;
import com.google.cloud.storage.testing.RemoteStorageHelper;
+import com.google.cloud.testing.junit4.StdOutCaptureRule;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import java.io.ByteArrayOutputStream;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
@@ -111,10 +108,11 @@ public class ITBucketSnippets {
private static final String KMS_KEY_NAME =
"projects/java-docs-samples-testing/locations/us/keyRings/"
+ "jds_test_kms_key_ring/cryptoKeys/gcs_kms_key_one";
- private final PrintStream standardOut = new PrintStream(new FileOutputStream(FileDescriptor.out));
private static Storage storage;
+ @Rule public final StdOutCaptureRule stdOutCaptureRule = new StdOutCaptureRule();
+
@Rule public ExpectedException thrown = ExpectedException.none();
@Rule public Timeout globalTimeout = Timeout.seconds(300);
@@ -152,9 +150,6 @@ public static void afterClass() throws ExecutionException, InterruptedException
public void after() throws Exception {
// This avoids 429 errors
Thread.sleep(3000);
-
- // This is just in case any tests failed before they could reset the value
- System.setOut(standardOut);
}
@Test
@@ -231,12 +226,8 @@ public void testGetBucketMetadata() {
.build()
.update();
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
GetBucketMetadata.getBucketMetadata(PROJECT_ID, BUCKET);
- String snippetOutput = snippetOutputCapture.toString();
- System.setOut(standardOut);
- System.out.println(snippetOutput);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains(("BucketName: " + bucket.getName())));
assertTrue(
snippetOutput.contains(("DefaultEventBasedHold: " + bucket.getDefaultEventBasedHold())));
@@ -264,11 +255,8 @@ public void testGetBucketMetadata() {
@Test
public void testListBuckets() {
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
ListBuckets.listBuckets(PROJECT_ID);
- String snippetOutput = snippetOutputCapture.toString();
- System.setOut(standardOut);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains(BUCKET));
}
@@ -320,11 +308,8 @@ public void testGetPublicAccessPrevention() {
.build())
.build()
.update();
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
GetPublicAccessPrevention.getPublicAccessPrevention(PROJECT_ID, BUCKET);
- String snippetOutput = snippetOutputCapture.toString();
- System.setOut(standardOut);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains("enforced"));
storage
.get(BUCKET)
@@ -421,11 +406,8 @@ public void testAddListRemoveBucketIamMembers() {
int originalSize = storage.getIamPolicy(BUCKET).getBindingsList().size();
AddBucketIamMember.addBucketIamMember(PROJECT_ID, BUCKET);
assertEquals(originalSize + 1, storage.getIamPolicy(BUCKET).getBindingsList().size());
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
ListBucketIamMembers.listBucketIamMembers(PROJECT_ID, BUCKET);
- String snippetOutput = snippetOutputCapture.toString();
- System.setOut(standardOut);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains("example@google.com"));
RemoveBucketIamMember.removeBucketIamMember(PROJECT_ID, BUCKET);
assertEquals(originalSize, storage.getIamPolicy(BUCKET).getBindingsList().size());
@@ -486,11 +468,8 @@ public void testSetBucketWebsiteInfo() {
@Test
public void testSetClientEndpoint() {
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
SetClientEndpoint.setClientEndpoint(PROJECT_ID, "https://storage.googleapis.com");
- String snippetOutput = snippetOutputCapture.toString();
- System.setOut(standardOut);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains("https://storage.googleapis.com"));
}
@@ -566,11 +545,8 @@ public void testRpo() throws Exception {
bucket = storage.get(rpoBucket);
assertEquals("ASYNC_TURBO", bucket.getRpo().toString());
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
GetBucketRpo.getBucketRpo(PROJECT_ID, rpoBucket);
- String snippetOutput = snippetOutputCapture.toString();
- System.setOut(standardOut);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains("ASYNC_TURBO"));
} finally {
storage.delete(rpoBucket);
@@ -594,21 +570,16 @@ public void testBucketRetention() {
assertEquals(retention, bucket.getRetentionPeriod());
assertNotNull(bucket.getRetentionEffectiveTime());
- ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
GetRetentionPolicy.getRetentionPolicy(PROJECT_ID, BUCKET);
- String snippetOutput = snippetOutputCapture.toString();
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains("5"));
EnableDefaultEventBasedHold.enableDefaultEventBasedHold(PROJECT_ID, BUCKET);
assertTrue(storage.get(BUCKET).getDefaultEventBasedHold());
- snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
GetDefaultEventBasedHold.getDefaultEventBasedHold(PROJECT_ID, BUCKET);
- snippetOutput = snippetOutputCapture.toString();
+ snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains("enabled"));
- System.setOut(standardOut);
byte[] content = {0xD, 0xE, 0xA, 0xD};
String blobName = "test-create-empty-blob-retention-policy";
@@ -645,12 +616,9 @@ public void testUniformBucketLevelAccess() {
assertTrue(bucket.getIamConfiguration().isUniformBucketLevelAccessEnabled());
assertNotNull(bucket.getIamConfiguration().getUniformBucketLevelAccessLockedTime());
- ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
GetUniformBucketLevelAccess.getUniformBucketLevelAccess(PROJECT_ID, BUCKET);
- String snippetOutput = snippetOutputCapture.toString();
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains("enabled"));
- System.setOut(standardOut);
DisableUniformBucketLevelAccess.disableUniformBucketLevelAccess(PROJECT_ID, BUCKET);
assertFalse(storage.get(BUCKET).getIamConfiguration().isUniformBucketLevelAccessEnabled());
diff --git a/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java b/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java
index 6c6886eb53..3cb572dc94 100644
--- a/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java
+++ b/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java
@@ -61,16 +61,13 @@
import com.google.cloud.storage.Storage.BlobListOption;
import com.google.cloud.storage.StorageClass;
import com.google.cloud.storage.testing.RemoteStorageHelper;
+import com.google.cloud.testing.junit4.StdOutCaptureRule;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.BaseEncoding;
-import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.PrintStream;
import java.net.URL;
import java.nio.file.Files;
import java.util.Date;
@@ -83,7 +80,6 @@
import javax.net.ssl.HttpsURLConnection;
import org.junit.AfterClass;
import org.junit.Assert;
-import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
@@ -97,13 +93,14 @@ public class ITObjectSnippets {
private static final String STRING_CONTENT = "Hello, World!";
private static final byte[] CONTENT = STRING_CONTENT.getBytes(UTF_8);
private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
- private final PrintStream standardOut = new PrintStream(new FileOutputStream(FileDescriptor.out));
private static final String KMS_KEY_NAME =
"projects/java-docs-samples-testing/locations/us/keyRings/"
+ "jds_test_kms_key_ring/cryptoKeys/gcs_kms_key_one";
private static Storage storage;
+ @Rule public final StdOutCaptureRule stdOutCaptureRule = new StdOutCaptureRule();
+
@Rule public ExpectedException thrown = ExpectedException.none();
@BeforeClass
@@ -127,12 +124,6 @@ public static void afterClass() throws ExecutionException, InterruptedException
}
}
- @Before
- public void before() {
- // This is just in case any tests failed before they could reset the value
- System.setOut(standardOut);
- }
-
@Test
public void testChangeObjectStorageClass() {
Blob blob = storage.get(BUCKET, BLOB);
@@ -177,12 +168,8 @@ public void testDownloadObject() throws IOException {
@Test
public void testDownloadObjectIntoMemory() throws IOException {
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
DownloadObjectIntoMemory.downloadObjectIntoMemory(PROJECT_ID, BUCKET, BLOB);
- String snippetOutput = snippetOutputCapture.toString();
- assertTrue(snippetOutput.contains("Hello, World!"));
- System.setOut(standardOut);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
}
@Test
@@ -207,12 +194,8 @@ public void testGetObjectMetadata() {
BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setMetadata(ImmutableMap.of("k", "v")).build();
Blob remoteBlob = storage.create(blobInfo, CONTENT);
assertNotNull(remoteBlob);
- final PrintStream systemOut = System.out;
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
GetObjectMetadata.getObjectMetadata(PROJECT_ID, BUCKET, blobName);
- String snippetOutput = snippetOutputCapture.toString();
- System.setOut(systemOut);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains("Bucket: " + remoteBlob.getBucket()));
assertTrue(snippetOutput.contains("Bucket: " + remoteBlob.getBucket()));
assertTrue(snippetOutput.contains("CacheControl: " + remoteBlob.getCacheControl()));
@@ -246,28 +229,21 @@ public void testGetObjectMetadata() {
@Test
public void testListObjects() {
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
ListObjects.listObjects(PROJECT_ID, BUCKET);
- String snippetOutput = snippetOutputCapture.toString();
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains(BLOB));
- System.setOut(standardOut);
}
@Test
public void testListObjectsWithPrefix() {
- final PrintStream systemOutput = System.out;
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
storage.create(BlobInfo.newBuilder(BlobId.of(BUCKET, "a/1.txt")).build());
storage.create(BlobInfo.newBuilder(BlobId.of(BUCKET, "a/b/2.txt")).build());
storage.create(BlobInfo.newBuilder(BlobId.of(BUCKET, "a/b/3.txt")).build());
ListObjectsWithPrefix.listObjectsWithPrefix(PROJECT_ID, BUCKET, "a/");
- String snippetOutput = snippetOutputCapture.toString();
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains("a/1.txt"));
assertTrue(snippetOutput.contains("a/b/"));
assertFalse(snippetOutput.contains("a/b/2.txt"));
- System.setOut(systemOutput);
}
@Test
@@ -318,13 +294,8 @@ public void testUploadObjectFromMemory() throws IOException {
@Test
public void testObjectCSEKOperations() throws IOException {
- final PrintStream systemOut = System.out;
-
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
GenerateEncryptionKey.generateEncryptionKey();
- String snippetOutput = snippetOutputCapture.toString();
- System.setOut(systemOut);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
String encryptionKey = snippetOutput.split(": ")[1].trim();
File tempFile = File.createTempFile("file", ".txt");
@@ -363,12 +334,8 @@ public void testObjectVersioningOperations() {
byte[] content2 = "Hello, World 2".getBytes(UTF_8);
storage.create(BlobInfo.newBuilder(BUCKET, versionedBlob).build(), content2);
- final PrintStream systemOut = System.out;
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
ListObjectsWithOldVersions.listObjectsWithOldVersions(PROJECT_ID, BUCKET);
- String snippetOutput = snippetOutputCapture.toString();
- System.setOut(systemOut);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
snippetOutput = snippetOutput.replaceFirst(versionedBlob, "");
assertTrue(snippetOutput.contains(versionedBlob));
@@ -386,10 +353,8 @@ public void testObjectVersioningOperations() {
@Test
public void testV4SignedURLs() throws IOException {
String tempObject = "test-upload-signed-url-object";
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
GenerateV4PutObjectSignedUrl.generateV4PutObjectSignedUrl(PROJECT_ID, BUCKET, tempObject);
- String snippetOutput = snippetOutputCapture.toString();
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
String url = snippetOutput.split("\n")[1];
URL uploadUrl = new URL(url);
HttpsURLConnection connection = (HttpsURLConnection) uploadUrl.openConnection();
@@ -401,10 +366,9 @@ public void testV4SignedURLs() throws IOException {
assertEquals(connection.getResponseCode(), 200);
}
GenerateV4GetObjectSignedUrl.generateV4GetObjectSignedUrl(PROJECT_ID, BUCKET, tempObject);
- snippetOutput = snippetOutputCapture.toString();
+ snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
url = snippetOutput.split("\n")[5];
URL downloadUrl = new URL(url);
- System.setOut(standardOut);
connection = (HttpsURLConnection) downloadUrl.openConnection();
byte[] readBytes = new byte[CONTENT.length];
try (InputStream responseStream = connection.getInputStream()) {
diff --git a/samples/snippets/src/test/java/com/example/storage/ITStorageSnippets.java b/samples/snippets/src/test/java/com/example/storage/ITStorageSnippets.java
index 092a681a7d..3c448def64 100644
--- a/samples/snippets/src/test/java/com/example/storage/ITStorageSnippets.java
+++ b/samples/snippets/src/test/java/com/example/storage/ITStorageSnippets.java
@@ -22,10 +22,9 @@
import com.google.cloud.storage.BucketInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.testing.RemoteStorageHelper;
-import java.io.ByteArrayOutputStream;
+import com.google.cloud.testing.junit4.StdOutCaptureRule;
import java.io.File;
import java.io.FileInputStream;
-import java.io.PrintStream;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
@@ -52,6 +51,8 @@ public class ITStorageSnippets {
private static Storage storage;
private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT");
+ @Rule public final StdOutCaptureRule stdOutCaptureRule = new StdOutCaptureRule();
+
@Rule public ExpectedException thrown = ExpectedException.none();
@Rule public Timeout globalTimeout = Timeout.seconds(300);
@@ -81,12 +82,8 @@ public static void afterClass() throws ExecutionException, InterruptedException
@Test
public void testGetServiceAccount() {
- PrintStream systemOut = System.out;
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
GetServiceAccount.getServiceAccount(PROJECT_ID);
- String snippetOutput = snippetOutputCapture.toString();
- System.setOut(systemOut);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(snippetOutput.contains("service"));
assertTrue(snippetOutput.contains("@gs-project-accounts.iam.gserviceaccount.com"));
@@ -94,12 +91,8 @@ public void testGetServiceAccount() {
@Test
public void testGenerateSignedPostPolicyV4() throws Exception {
- PrintStream systemOut = System.out;
- final ByteArrayOutputStream snippetOutputCapture = new ByteArrayOutputStream();
- System.setOut(new PrintStream(snippetOutputCapture));
GenerateSignedPostPolicyV4.generateSignedPostPolicyV4(PROJECT_ID, BUCKET, "my-object");
- String snippetOutput = snippetOutputCapture.toString();
- System.setOut(systemOut);
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
assertTrue(
snippetOutput.contains("