> resolveSettingsAndOpts() throw
// for reads, the stream can be held open for a long time in order to read all bytes,
// this is totally valid. instead we want to monitor if the stream is doing work and if not
// timeout.
- .setIdleTimeout(totalTimeout);
+ .setIdleTimeoutDuration(totalTimeout);
return Tuple.of(builder.build(), defaultOpts);
}
@@ -412,7 +415,7 @@ protected boolean shouldRefreshService(Storage cachedService) {
public static final class Builder extends StorageOptions.Builder {
private StorageRetryStrategy storageRetryStrategy;
- private Duration terminationAwaitDuration;
+ private java.time.Duration terminationAwaitDuration;
private boolean attemptDirectPath = GrpcStorageDefaults.INSTANCE.isAttemptDirectPath();
private boolean enableGrpcClientMetrics =
GrpcStorageDefaults.INSTANCE.isEnableGrpcClientMetrics();
@@ -436,6 +439,15 @@ public static final class Builder extends StorageOptions.Builder {
this.blobWriteSessionConfig = gso.blobWriteSessionConfig;
}
+ /**
+ * This method is obsolete. Use {@link #setTerminationAwaitJavaTimeDuration(java.time.Duration)}
+ * instead.
+ */
+ @ObsoleteApi("Use setTerminationAwaitJavaTimeDuration(java.time.Duration) instead")
+ public Builder setTerminationAwaitDuration(org.threeten.bp.Duration terminationAwaitDuration) {
+ return setTerminationAwaitJavaTimeDuration(toJavaTimeDuration(terminationAwaitDuration));
+ }
+
/**
* Set the maximum duration in which to await termination of any outstanding requests when
* calling {@link Storage#close()}
@@ -444,7 +456,8 @@ public static final class Builder extends StorageOptions.Builder {
* @return the builder
* @since 2.14.0
*/
- public Builder setTerminationAwaitDuration(Duration terminationAwaitDuration) {
+ public Builder setTerminationAwaitJavaTimeDuration(
+ java.time.Duration terminationAwaitDuration) {
this.terminationAwaitDuration =
requireNonNull(terminationAwaitDuration, "terminationAwaitDuration must be non null");
return this;
@@ -652,9 +665,15 @@ public StorageRetryStrategy getStorageRetryStrategy() {
return StorageRetryStrategy.getDefaultStorageRetryStrategy();
}
+ /** This method is obsolete. Use {@link #getTerminationAwaitDurationJavaTime()} instead. */
+ @ObsoleteApi("Use getTerminationAwaitDurationJavaTime() instead")
+ public org.threeten.bp.Duration getTerminationAwaitDuration() {
+ return toThreetenDuration(getTerminationAwaitDurationJavaTime());
+ }
+
/** @since 2.14.0 */
- public Duration getTerminationAwaitDuration() {
- return Duration.ofMinutes(1);
+ public java.time.Duration getTerminationAwaitDurationJavaTime() {
+ return java.time.Duration.ofMinutes(1);
}
/** @since 2.14.0 */
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/RemoteStorageHelper.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/RemoteStorageHelper.java
index 50bfdc8743..2d604a287c 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/RemoteStorageHelper.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/RemoteStorageHelper.java
@@ -32,6 +32,7 @@
import com.google.common.base.Strings;
import java.io.IOException;
import java.io.InputStream;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -44,7 +45,6 @@
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
-import org.threeten.bp.Duration;
/**
* Utility to create a remote storage configuration for testing. Storage options can be obtained via
@@ -233,13 +233,13 @@ public static RemoteStorageHelper create() throws StorageHelperException {
private static RetrySettings retrySettings() {
return RetrySettings.newBuilder()
.setMaxAttempts(10)
- .setMaxRetryDelay(Duration.ofMillis(30000L))
- .setTotalTimeout(Duration.ofMillis(120000L))
- .setInitialRetryDelay(Duration.ofMillis(250L))
+ .setMaxRetryDelayDuration(Duration.ofMillis(30000L))
+ .setTotalTimeoutDuration(Duration.ofMillis(120000L))
+ .setInitialRetryDelayDuration(Duration.ofMillis(250L))
.setRetryDelayMultiplier(1.0)
- .setInitialRpcTimeout(Duration.ofMillis(120000L))
+ .setInitialRpcTimeoutDuration(Duration.ofMillis(120000L))
.setRpcTimeoutMultiplier(1.0)
- .setMaxRpcTimeout(Duration.ofMillis(120000L))
+ .setMaxRpcTimeoutDuration(Duration.ofMillis(120000L))
.build();
}
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicReadTimeoutTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicReadTimeoutTest.java
index 9cef9159c0..40cf755c97 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicReadTimeoutTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/ITGapicReadTimeoutTest.java
@@ -36,10 +36,10 @@
import io.grpc.Status.Code;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
+import java.time.Duration;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
-import org.threeten.bp.Duration;
/**
* ReadObject leverages gRPC ServerStream to read a stream of ReadObjectResponse messages spanning
@@ -48,7 +48,7 @@
* #getTotalTimeout()}, gax will interrupt the stream with a DEADLINE_EXCEEDED error.
*
* Instead of relying on total stream timeout, we rely on idleTimeout for the stream via {@link
- * com.google.api.gax.rpc.ServerStreamingCallSettings.Builder#setIdleTimeout(Duration)}.
+ * com.google.api.gax.rpc.ServerStreamingCallSettings.Builder#setIdleTimeoutDuration(Duration)}.
*
*
These tests force specific timeout scenarios to happen against an in-process grpc server to
* ensure our configuration of the StorageClient properly translates to the behavior we want.
@@ -117,7 +117,7 @@ public void readObject(
.setRetrySettings(
RetrySettings.newBuilder()
.setMaxAttempts(3)
- .setTotalTimeout(Duration.ofMillis(totalTimeoutMillis))
+ .setTotalTimeoutDuration(Duration.ofMillis(totalTimeoutMillis))
.build())
.build()
.getStorageSettings();
@@ -196,7 +196,7 @@ public void readObject(
.setRetrySettings(
RetrySettings.newBuilder()
.setMaxAttempts(3)
- .setTotalTimeout(Duration.ofMillis(totalTimeoutMillis))
+ .setTotalTimeoutDuration(Duration.ofMillis(totalTimeoutMillis))
.build())
.build()
.getStorageSettings();
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/conformance/retry/RpcMethodMappings.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/conformance/retry/RpcMethodMappings.java
index 7db8c2cf18..6caecc5c76 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/conformance/retry/RpcMethodMappings.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/conformance/retry/RpcMethodMappings.java
@@ -1283,20 +1283,18 @@ private static void get(ArrayList a) {
(ctx, c) ->
ctx.peek(
state -> {
- try {
- ReadChannel reader =
- ctx.getStorage().reader(ctx.getState().getBlob().getBlobId());
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (ReadChannel reader =
+ ctx.getStorage().reader(ctx.getState().getBlob().getBlobId())) {
WritableByteChannel write = Channels.newChannel(baos);
ByteStreams.copy(reader, write);
-
- assertThat(xxd(baos.toByteArray()))
- .isEqualTo(xxd(c.getHelloWorldUtf8Bytes()));
} catch (IOException e) {
if (e.getCause() instanceof BaseServiceException) {
throw e.getCause();
}
}
+ assertThat(xxd(baos.toByteArray()))
+ .isEqualTo(xxd(c.getHelloWorldUtf8Bytes()));
}))
.build());
a.add(
@@ -1305,23 +1303,46 @@ private static void get(ArrayList a) {
(ctx, c) ->
ctx.peek(
state -> {
- try {
- ReadChannel reader =
- ctx.getStorage()
- .reader(
- ctx.getState().getBlob().getBlobId().getBucket(),
- ctx.getState().getBlob().getBlobId().getName());
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (ReadChannel reader =
+ ctx.getStorage()
+ .reader(
+ ctx.getState().getBlob().getBlobId().getBucket(),
+ ctx.getState().getBlob().getBlobId().getName())) {
WritableByteChannel write = Channels.newChannel(baos);
ByteStreams.copy(reader, write);
+ } catch (IOException e) {
+ if (e.getCause() instanceof BaseServiceException) {
+ throw e.getCause();
+ }
+ }
- assertThat(xxd(baos.toByteArray()))
- .isEqualTo(xxd(c.getHelloWorldUtf8Bytes()));
+ assertThat(xxd(baos.toByteArray()))
+ .isEqualTo(xxd(c.getHelloWorldUtf8Bytes()));
+ }))
+ .build());
+ a.add(
+ RpcMethodMapping.newBuilder(250, objects.get)
+ .withTest(
+ (ctx, c) ->
+ ctx.peek(
+ state -> {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (ReadChannel reader =
+ ctx.getStorage()
+ .reader(
+ ctx.getState().getBlob().getBlobId(),
+ BlobSourceOption.shouldReturnRawInputStream(false))) {
+ WritableByteChannel write = Channels.newChannel(baos);
+ ByteStreams.copy(reader, write);
} catch (IOException e) {
if (e.getCause() instanceof BaseServiceException) {
throw e.getCause();
}
}
+
+ assertThat(xxd(baos.toByteArray()))
+ .isEqualTo(xxd(c.getHelloWorldUtf8Bytes()));
}))
.build());
a.add(
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteChannelTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteChannelTest.java
index 9695232b86..2a2dd9a665 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteChannelTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITBlobWriteChannelTest.java
@@ -55,16 +55,16 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Optional;
import java.util.logging.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.threeten.bp.Clock;
-import org.threeten.bp.Instant;
-import org.threeten.bp.ZoneId;
-import org.threeten.bp.ZoneOffset;
-import org.threeten.bp.format.DateTimeFormatter;
@RunWith(StorageITRunner.class)
@SingleBackend(Backend.TEST_BENCH)
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITHmacTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITHmacTest.java
index 36239edc5a..191514570e 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITHmacTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITHmacTest.java
@@ -32,11 +32,11 @@
import com.google.cloud.storage.it.runner.annotations.Backend;
import com.google.cloud.storage.it.runner.annotations.CrossRun;
import com.google.cloud.storage.it.runner.annotations.Inject;
+import java.time.Duration;
+import java.time.Instant;
import java.util.stream.StreamSupport;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.threeten.bp.Duration;
-import org.threeten.bp.Instant;
@RunWith(StorageITRunner.class)
@CrossRun(
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/TestBench.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/TestBench.java
index 8a58a07212..d40a29954d 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/TestBench.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/runner/registry/TestBench.java
@@ -53,6 +53,7 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.time.Duration;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@@ -60,7 +61,6 @@
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.threeten.bp.Duration;
/**
* A {@link ManagedLifecycle} which integrates with the >() {
@Override
@@ -335,10 +335,10 @@ public void stop() {
throw new NotShutdownException();
},
RetrySettings.newBuilder()
- .setTotalTimeout(Duration.ofSeconds(30))
- .setInitialRetryDelay(Duration.ofMillis(500))
+ .setTotalTimeoutDuration(Duration.ofSeconds(30))
+ .setInitialRetryDelayDuration(Duration.ofMillis(500))
.setRetryDelayMultiplier(1.5)
- .setMaxRetryDelay(Duration.ofSeconds(5))
+ .setMaxRetryDelayDuration(Duration.ofSeconds(5))
.build(),
new BasicResultRetryAlgorithm>() {
@Override
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/RemoteStorageHelperTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/RemoteStorageHelperTest.java
index 508109e3e2..61e9574ed2 100644
--- a/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/RemoteStorageHelperTest.java
+++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/RemoteStorageHelperTest.java
@@ -34,6 +34,7 @@
import com.google.common.collect.ImmutableList;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -43,7 +44,6 @@
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
-import org.threeten.bp.Duration;
public class RemoteStorageHelperTest {
@@ -273,8 +273,8 @@ public void testCreateFromStream() {
assertEquals(60000, ((HttpTransportOptions) options.getTransportOptions()).getConnectTimeout());
assertEquals(60000, ((HttpTransportOptions) options.getTransportOptions()).getReadTimeout());
assertEquals(10, options.getRetrySettings().getMaxAttempts());
- assertEquals(Duration.ofMillis(30000), options.getRetrySettings().getMaxRetryDelay());
- assertEquals(Duration.ofMillis(120000), options.getRetrySettings().getTotalTimeout());
- assertEquals(Duration.ofMillis(250), options.getRetrySettings().getInitialRetryDelay());
+ assertEquals(Duration.ofMillis(30000), options.getRetrySettings().getMaxRetryDelayDuration());
+ assertEquals(Duration.ofMillis(120000), options.getRetrySettings().getTotalTimeoutDuration());
+ assertEquals(Duration.ofMillis(250), options.getRetrySettings().getInitialRetryDelayDuration());
}
}
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 d372c53395..b9a2c50546 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.49.0
+FROM gcr.io/cloud-devrel-public-resources/storage-testbench:v0.50.0
diff --git a/grpc-google-cloud-storage-control-v2/pom.xml b/grpc-google-cloud-storage-control-v2/pom.xml
index 151f650614..21af1ce86f 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.45.0
+ 2.46.0
grpc-google-cloud-storage-control-v2
GRPC library for google-cloud-storage
com.google.cloud
google-cloud-storage-parent
- 2.45.0
+ 2.46.0
diff --git a/grpc-google-cloud-storage-v2/pom.xml b/grpc-google-cloud-storage-v2/pom.xml
index 4a9adeabdb..ef457a44b5 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.45.0-beta
+ 2.46.0-beta
grpc-google-cloud-storage-v2
GRPC library for grpc-google-cloud-storage-v2
com.google.cloud
google-cloud-storage-parent
- 2.45.0
+ 2.46.0
diff --git a/pom.xml b/pom.xml
index e4cc7478aa..e2c8f1fcda 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.google.cloud
google-cloud-storage-parent
pom
- 2.45.0
+ 2.46.0
Storage Parent
https://github.com/googleapis/java-storage
@@ -14,7 +14,7 @@
com.google.cloud
sdk-platform-java-config
- 3.40.0
+ 3.41.0
@@ -84,18 +84,7 @@
io.opentelemetry.semconv
opentelemetry-semconv
- 1.25.0-alpha
-
-
- com.google.cloud.opentelemetry
- exporter-metrics
- 0.31.0
-
-
- io.opentelemetry.semconv
- opentelemetry-semconv
-
-
+ 1.27.0-alpha
com.google.cloud.opentelemetry
@@ -134,17 +123,17 @@
com.google.cloud
google-cloud-storage
- 2.45.0
+ 2.46.0
com.google.apis
google-api-services-storage
- v1-rev20241008-2.0.0
+ v1-rev20241206-2.0.0
com.google.cloud
google-cloud-pubsub
- 1.134.1
+ 1.135.0
test
@@ -156,32 +145,32 @@
com.google.api.grpc
proto-google-cloud-storage-v2
- 2.45.0-beta
+ 2.46.0-beta
com.google.api.grpc
grpc-google-cloud-storage-v2
- 2.45.0-beta
+ 2.46.0-beta
com.google.api.grpc
gapic-google-cloud-storage-v2
- 2.45.0-beta
+ 2.46.0-beta
com.google.api.grpc
grpc-google-cloud-storage-control-v2
- 2.45.0
+ 2.46.0
com.google.api.grpc
proto-google-cloud-storage-control-v2
- 2.45.0
+ 2.46.0
com.google.cloud
google-cloud-storage-control
- 2.45.0
+ 2.46.0
com.google.cloud
diff --git a/proto-google-cloud-storage-control-v2/pom.xml b/proto-google-cloud-storage-control-v2/pom.xml
index 636a7eae6a..570ef5d7c7 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.45.0
+ 2.46.0
proto-google-cloud-storage-control-v2
Proto library for proto-google-cloud-storage-control-v2
com.google.cloud
google-cloud-storage-parent
- 2.45.0
+ 2.46.0
diff --git a/proto-google-cloud-storage-v2/pom.xml b/proto-google-cloud-storage-v2/pom.xml
index 741784e7b4..cac0db77d7 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.45.0-beta
+ 2.46.0-beta
proto-google-cloud-storage-v2
PROTO library for proto-google-cloud-storage-v2
com.google.cloud
google-cloud-storage-parent
- 2.45.0
+ 2.46.0
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index f4c6bf4ce0..464e55405b 100644
--- a/samples/install-without-bom/pom.xml
+++ b/samples/install-without-bom/pom.xml
@@ -30,12 +30,12 @@
com.google.cloud
google-cloud-storage
- 2.44.1
+ 2.45.0
com.google.cloud
google-cloud-storage-control
- 2.44.1
+ 2.45.0
@@ -66,13 +66,13 @@
com.google.cloud
google-cloud-pubsub
- 1.134.1
+ 1.135.0
test
com.google.cloud
google-cloud-storage
- 2.44.1
+ 2.45.0
tests
test
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index aa286d1d59..c7235dbd03 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -28,12 +28,12 @@
com.google.cloud
google-cloud-storage
- 2.45.0
+ 2.46.0
com.google.cloud
google-cloud-storage-control
- 2.45.0
+ 2.46.0
compile
@@ -58,13 +58,13 @@
com.google.cloud
google-cloud-pubsub
- 1.134.1
+ 1.135.0
test
com.google.cloud
google-cloud-storage
- 2.45.0
+ 2.46.0
tests
test
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 0ca18023f9..0370729e59 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -31,7 +31,7 @@
com.google.cloud
libraries-bom
- 26.50.0
+ 26.51.0
pom
import
@@ -76,14 +76,14 @@
com.google.cloud
google-cloud-pubsub
- 1.134.1
+ 1.135.0
test
com.google.cloud
google-cloud-storage
- 2.44.1
+ 2.45.0
tests
test
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/DisableSoftDelete.java b/samples/snippets/src/main/java/com/example/storage/bucket/DisableSoftDelete.java
new file mode 100644
index 0000000000..eeb9021c32
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/DisableSoftDelete.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2024 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_disable_soft_delete]
+import com.google.cloud.storage.Bucket;
+import com.google.cloud.storage.BucketInfo;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+import java.time.Duration;
+
+public class DisableSoftDelete {
+ public static void disableSoftDelete(String projectId, String bucketName) {
+ // The ID of your GCP project
+ // String projectId = "your-project-id";
+
+ // The ID of your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
+ Bucket bucket = storage.get(bucketName);
+ bucket
+ .toBuilder()
+ .setSoftDeletePolicy(
+ // Setting the retention duration to 0 disables Soft Delete.
+ BucketInfo.SoftDeletePolicy.newBuilder()
+ .setRetentionDuration(Duration.ofSeconds(0))
+ .build())
+ .build()
+ .update();
+
+ System.out.println("Soft delete for " + bucketName + " was disabled");
+ }
+}
+// [END storage_disable_soft_delete]
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/GetSoftDeletePolicy.java b/samples/snippets/src/main/java/com/example/storage/bucket/GetSoftDeletePolicy.java
new file mode 100644
index 0000000000..32f4277a05
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/GetSoftDeletePolicy.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2024 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_get_soft_delete_policy]
+import com.google.cloud.storage.BucketInfo.SoftDeletePolicy;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+import java.time.Duration;
+
+public class GetSoftDeletePolicy {
+ public static void getSoftDeletePolicy(String projectId, String bucketName) {
+ // The ID of your GCP project
+ // String projectId = "your-project-id";
+
+ // The ID of your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
+ SoftDeletePolicy policy = storage.get(bucketName).getSoftDeletePolicy();
+
+ if (Duration.ofSeconds(0).equals(policy.getRetentionDuration())) {
+ System.out.println("Soft delete is disabled for " + bucketName);
+ } else {
+ System.out.println("The soft delete policy for " + bucketName + " is:");
+ System.out.println(policy);
+ }
+ }
+}
+// [END storage_get_soft_delete_policy]
diff --git a/samples/snippets/src/main/java/com/example/storage/bucket/SetSoftDeletePolicy.java b/samples/snippets/src/main/java/com/example/storage/bucket/SetSoftDeletePolicy.java
new file mode 100644
index 0000000000..17dfb38301
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/bucket/SetSoftDeletePolicy.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2024 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_set_soft_delete_policy]
+import com.google.cloud.storage.Bucket;
+import com.google.cloud.storage.BucketInfo;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+import java.time.Duration;
+
+public class SetSoftDeletePolicy {
+ public static void setSoftDeletePolicy(String projectId, String bucketName) {
+ // The ID of your GCP project
+ // String projectId = "your-project-id";
+
+ // The ID of your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
+ Bucket bucket = storage.get(bucketName);
+ bucket
+ .toBuilder()
+ .setSoftDeletePolicy(
+ BucketInfo.SoftDeletePolicy.newBuilder()
+ .setRetentionDuration(Duration.ofDays(10))
+ .build())
+ .build()
+ .update();
+
+ System.out.println(
+ "Soft delete policy for " + bucketName + " was set to a 10-day retention period");
+ }
+}
+// [END storage_set_soft_delete_policy]
diff --git a/samples/snippets/src/main/java/com/example/storage/object/ListSoftDeletedObjects.java b/samples/snippets/src/main/java/com/example/storage/object/ListSoftDeletedObjects.java
new file mode 100644
index 0000000000..eb3b5d158b
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/object/ListSoftDeletedObjects.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2024 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.object;
+
+// [START storage_list_soft_deleted_objects]
+import com.google.api.gax.paging.Page;
+import com.google.cloud.storage.Blob;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+
+public class ListSoftDeletedObjects {
+ public static void listSoftDeletedObjects(String projectId, String bucketName) {
+ // The ID of your GCP project
+ // String projectId = "your-project-id";
+
+ // The ID of your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
+ Page blobs = storage.list(bucketName, Storage.BlobListOption.softDeleted(true));
+
+ for (Blob blob : blobs.iterateAll()) {
+ System.out.println(blob.getName());
+ }
+ }
+}
+// [END storage_list_soft_deleted_objects]
diff --git a/samples/snippets/src/main/java/com/example/storage/object/ListSoftDeletedVersionsOfObject.java b/samples/snippets/src/main/java/com/example/storage/object/ListSoftDeletedVersionsOfObject.java
new file mode 100644
index 0000000000..87532cdc8e
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/object/ListSoftDeletedVersionsOfObject.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2024 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.object;
+
+// [START storage_list_soft_deleted_object_versions]
+import com.google.api.gax.paging.Page;
+import com.google.cloud.storage.Blob;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+
+public class ListSoftDeletedVersionsOfObject {
+
+ public static void listSoftDeletedVersionOfObject(
+ String projectId, String bucketName, String objectName) {
+ // The ID of your GCP project
+ // String projectId = "your-project-id";
+
+ // The ID of your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ // The name of your GCS object
+ // String objectName = "your-object-name";
+
+ Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
+ Page blobs =
+ storage.list(
+ bucketName,
+ Storage.BlobListOption.softDeleted(true),
+ // See https://cloud.google.com/storage/docs/json_api/v1/objects/list#matchGlob
+ Storage.BlobListOption.matchGlob(objectName));
+
+ for (Blob blob : blobs.iterateAll()) {
+ System.out.println(blob.getName());
+ }
+ }
+}
+// [END storage_list_soft_deleted_object_versions]
diff --git a/samples/snippets/src/main/java/com/example/storage/object/RestoreSoftDeletedObject.java b/samples/snippets/src/main/java/com/example/storage/object/RestoreSoftDeletedObject.java
new file mode 100644
index 0000000000..86f09a39ec
--- /dev/null
+++ b/samples/snippets/src/main/java/com/example/storage/object/RestoreSoftDeletedObject.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2024 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.object;
+
+// [START storage_restore_object]
+import com.google.cloud.storage.Blob;
+import com.google.cloud.storage.BlobId;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+
+public class RestoreSoftDeletedObject {
+ public static void restoreSoftDeletedObject(
+ String projectId, String bucketName, String objectName, long generation) {
+ // The ID of your GCP project
+ // String projectId = "your-project-id";
+
+ // The ID of your GCS bucket
+ // String bucketName = "your-unique-bucket-name";
+
+ // The name of your GCS object
+ // String objectName = "your-object-name";
+
+ Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
+ Blob blob = storage.restore(BlobId.of(bucketName, objectName, generation));
+
+ System.out.println("Restored previously soft-deleted object " + blob.getName());
+ }
+}
+// [END storage_restore_object]
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 2c10e71ff7..6bc256c0ff 100644
--- a/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java
+++ b/samples/snippets/src/test/java/com/example/storage/ITBucketSnippets.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -38,6 +39,7 @@
import com.example.storage.bucket.DisableDefaultEventBasedHold;
import com.example.storage.bucket.DisableLifecycleManagement;
import com.example.storage.bucket.DisableRequesterPays;
+import com.example.storage.bucket.DisableSoftDelete;
import com.example.storage.bucket.DisableUniformBucketLevelAccess;
import com.example.storage.bucket.EnableBucketVersioning;
import com.example.storage.bucket.EnableDefaultEventBasedHold;
@@ -68,6 +70,7 @@
import com.example.storage.bucket.SetPublicAccessPreventionEnforced;
import com.example.storage.bucket.SetPublicAccessPreventionInherited;
import com.example.storage.bucket.SetRetentionPolicy;
+import com.example.storage.bucket.SetSoftDeletePolicy;
import com.example.storage.object.DownloadRequesterPaysObject;
import com.example.storage.object.ReleaseEventBasedHold;
import com.example.storage.object.ReleaseTemporaryHold;
@@ -697,4 +700,36 @@ public void testCreateBucketWithObjectRetention() {
storage.delete(tempBucket);
}
}
+
+ @Test
+ public void testSetSoftDeletePolicy() {
+ String tempBucket = RemoteStorageHelper.generateBucketName();
+ Bucket bucket = storage.create(BucketInfo.of(tempBucket));
+ try {
+ assertNotEquals(
+ java.time.Duration.ofDays(10), bucket.getSoftDeletePolicy().getRetentionDuration());
+ SetSoftDeletePolicy.setSoftDeletePolicy(PROJECT_ID, tempBucket);
+ assertEquals(
+ java.time.Duration.ofDays(10),
+ storage.get(tempBucket).getSoftDeletePolicy().getRetentionDuration());
+ } finally {
+ storage.delete(tempBucket);
+ }
+ }
+
+ @Test
+ public void testDisableSoftDelete() {
+ String tempBucket = RemoteStorageHelper.generateBucketName();
+ Bucket bucket = storage.create(BucketInfo.of(tempBucket));
+ try {
+ assertNotEquals(
+ java.time.Duration.ofDays(0), bucket.getSoftDeletePolicy().getRetentionDuration());
+ DisableSoftDelete.disableSoftDelete(PROJECT_ID, tempBucket);
+ assertEquals(
+ java.time.Duration.ofSeconds(0),
+ storage.get(tempBucket).getSoftDeletePolicy().getRetentionDuration());
+ } finally {
+ storage.delete(tempBucket);
+ }
+ }
}
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 3fdb0cfe88..d9a2ccfba5 100644
--- a/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java
+++ b/samples/snippets/src/test/java/com/example/storage/ITObjectSnippets.java
@@ -43,8 +43,11 @@
import com.example.storage.object.ListObjects;
import com.example.storage.object.ListObjectsWithOldVersions;
import com.example.storage.object.ListObjectsWithPrefix;
+import com.example.storage.object.ListSoftDeletedObjects;
+import com.example.storage.object.ListSoftDeletedVersionsOfObject;
import com.example.storage.object.MakeObjectPublic;
import com.example.storage.object.MoveObject;
+import com.example.storage.object.RestoreSoftDeletedObject;
import com.example.storage.object.RotateObjectEncryptionKey;
import com.example.storage.object.SetObjectMetadata;
import com.example.storage.object.SetObjectRetentionPolicy;
@@ -73,6 +76,7 @@
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Files;
+import java.time.Duration;
import java.util.Date;
import java.util.Map;
import java.util.Random;
@@ -451,4 +455,92 @@ public void testSetObjectRetentionPolicy() {
storage.delete(tempBucket);
}
}
+
+ @Test
+ public void testListSoftDeletedObjects() {
+ // This is already the default, but we set it here in case the default ever changes
+ storage
+ .get(BUCKET)
+ .toBuilder()
+ .setSoftDeletePolicy(
+ BucketInfo.SoftDeletePolicy.newBuilder()
+ .setRetentionDuration(Duration.ofDays(7))
+ .build())
+ .build()
+ .update();
+
+ String blob = "softdelobj";
+ storage.create(BlobInfo.newBuilder(BlobId.of(BUCKET, blob)).build());
+ storage.delete(BlobId.of(BUCKET, blob));
+
+ ListSoftDeletedObjects.listSoftDeletedObjects(PROJECT_ID, BUCKET);
+
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
+
+ assertTrue(snippetOutput.contains(blob));
+ }
+
+ @Test
+ public void testListSoftDeletedVersionsOfObject() {
+ // This is already the default, but we set it here in case the default ever changes
+ storage
+ .get(BUCKET)
+ .toBuilder()
+ .setSoftDeletePolicy(
+ BucketInfo.SoftDeletePolicy.newBuilder()
+ .setRetentionDuration(Duration.ofDays(7))
+ .build())
+ .build()
+ .update();
+
+ System.out.println(storage.get(BUCKET).getSoftDeletePolicy().toString());
+
+ String blob = "softdelobj1";
+ storage.create(BlobInfo.newBuilder(BlobId.of(BUCKET, blob)).build());
+ storage.delete(BlobId.of(BUCKET, blob));
+
+ String blob2 = "softdelobj2";
+ storage.create(BlobInfo.newBuilder(BlobId.of(BUCKET, blob2)).build());
+ storage.delete(BlobId.of(BUCKET, blob2));
+
+ ListSoftDeletedVersionsOfObject.listSoftDeletedVersionOfObject(PROJECT_ID, BUCKET, blob);
+
+ String snippetOutput = stdOutCaptureRule.getCapturedOutputAsUtf8String();
+
+ assertTrue(snippetOutput.contains(blob));
+ assertFalse(snippetOutput.contains(blob2));
+ }
+
+ @Test
+ public void testRestoreSoftDeletedObject() {
+ String bucket = RemoteStorageHelper.generateBucketName();
+
+ storage.create(BucketInfo.of(bucket));
+ try {
+ // This is already the default, but we set it here in case the default ever changes
+ storage
+ .get(bucket)
+ .toBuilder()
+ .setSoftDeletePolicy(
+ BucketInfo.SoftDeletePolicy.newBuilder()
+ .setRetentionDuration(Duration.ofDays(7))
+ .build())
+ .build()
+ .update();
+
+ String blob = "restorableobj";
+
+ long gen =
+ storage.create(BlobInfo.newBuilder(BlobId.of(bucket, blob)).build()).getGeneration();
+ storage.delete(BlobId.of(bucket, blob));
+
+ assertNull(storage.get(BlobId.of(bucket, blob)));
+
+ RestoreSoftDeletedObject.restoreSoftDeletedObject(PROJECT_ID, bucket, blob, gen);
+
+ assertNotNull(storage.get(BlobId.of(bucket, blob)));
+ } finally {
+ RemoteStorageHelper.forceDelete(storage, bucket);
+ }
+ }
}
diff --git a/storage-shared-benchmarking/pom.xml b/storage-shared-benchmarking/pom.xml
index 09c97dfdfd..41a711ecf2 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.45.0
+ 2.46.0
@@ -31,7 +31,7 @@
com.google.cloud
google-cloud-storage
- 2.45.0
+ 2.46.0
tests
diff --git a/versions.txt b/versions.txt
index 4a27acbd91..fe6840580c 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,10 +1,10 @@
# Format:
# module:released-version:current-version
-google-cloud-storage:2.45.0:2.45.0
-gapic-google-cloud-storage-v2:2.45.0-beta:2.45.0-beta
-grpc-google-cloud-storage-v2:2.45.0-beta:2.45.0-beta
-proto-google-cloud-storage-v2:2.45.0-beta:2.45.0-beta
-google-cloud-storage-control:2.45.0:2.45.0
-proto-google-cloud-storage-control-v2:2.45.0:2.45.0
-grpc-google-cloud-storage-control-v2:2.45.0:2.45.0
+google-cloud-storage:2.46.0:2.46.0
+gapic-google-cloud-storage-v2:2.46.0-beta:2.46.0-beta
+grpc-google-cloud-storage-v2:2.46.0-beta:2.46.0-beta
+proto-google-cloud-storage-v2:2.46.0-beta:2.46.0-beta
+google-cloud-storage-control:2.46.0:2.46.0
+proto-google-cloud-storage-control-v2:2.46.0:2.46.0
+grpc-google-cloud-storage-control-v2:2.46.0:2.46.0