Skip to content

Commit 3deb29b

Browse files
JesseLovelacegcf-owl-bot[bot]BenWhitehead
authored
feat: add object retention feature (#2277)
* feat: add object retention feature * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * address review comments * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * Add a workaround to avoid a testbench failure * chore: some fixes from pairing with jesse * chore: put a `!` :don't program while sleepy: * chore: mvn-fmt * add a way to avoid using the objectRetentionField in bucket tests * add retention to blobfield tests * clirr and fmt * add todos * fmt --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com> Co-authored-by: BenWhitehead <BenWhitehead@users.noreply.github.com>
1 parent 6d26d14 commit 3deb29b

19 files changed

+548
-21
lines changed

google-cloud-storage/clirr-ignored-differences.xml

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@
1515
<method>* writeAndClose(*)</method>
1616
</difference>
1717

18+
<difference>
19+
<differenceType>7013</differenceType>
20+
<className>com/google/cloud/storage/BlobInfo$Builder</className>
21+
<method>com.google.cloud.storage.BlobInfo$Builder setRetention(com.google.cloud.storage.BlobInfo$Retention)</method>
22+
</difference>
23+
1824
<!-- @BetaApi members -->
1925
<difference>
2026
<differenceType>7009</differenceType>

google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java

+6
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,12 @@ Builder setRetentionExpirationTimeOffsetDateTime(OffsetDateTime retentionExpirat
526526
return this;
527527
}
528528

529+
@Override
530+
public Builder setRetention(Retention retention) {
531+
infoBuilder.setRetention(retention);
532+
return this;
533+
}
534+
529535
@Override
530536
public Blob build() {
531537
return new Blob(storage, infoBuilder);

google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java

+138-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@
2222
import static com.google.common.base.Preconditions.checkNotNull;
2323

2424
import com.google.api.client.util.Data;
25+
import com.google.api.core.ApiFunction;
2526
import com.google.api.core.BetaApi;
27+
import com.google.cloud.StringEnumType;
28+
import com.google.cloud.StringEnumValue;
2629
import com.google.cloud.storage.Storage.BlobField;
2730
import com.google.cloud.storage.TransportCompatibility.Transport;
2831
import com.google.cloud.storage.UnifiedOpts.NamedField;
@@ -104,6 +107,7 @@ public class BlobInfo implements Serializable {
104107
private final Boolean eventBasedHold;
105108
private final Boolean temporaryHold;
106109
private final OffsetDateTime retentionExpirationTime;
110+
private final Retention retention;
107111
private final transient ImmutableSet<NamedField> modifiedFields;
108112

109113
/** This class is meant for internal use only. Users are discouraged from using this class. */
@@ -168,6 +172,119 @@ public final boolean equals(Object o) {
168172
}
169173
}
170174

175+
/**
176+
* Defines a blob's Retention policy. Can only be used on objects in a retention-enabled bucket.
177+
*/
178+
public static final class Retention implements Serializable {
179+
180+
private static final long serialVersionUID = 5046718464542688444L;
181+
182+
private Mode mode;
183+
184+
private OffsetDateTime retainUntilTime;
185+
186+
/** Returns the retention policy's Mode. Can be Locked or Unlocked. */
187+
public Mode getMode() {
188+
return mode;
189+
}
190+
191+
/** Returns what time this object will be retained until, if the mode is Locked. */
192+
public OffsetDateTime getRetainUntilTime() {
193+
return retainUntilTime;
194+
}
195+
196+
@Override
197+
public boolean equals(Object o) {
198+
if (this == o) {
199+
return true;
200+
}
201+
if (!(o instanceof Retention)) {
202+
return false;
203+
}
204+
Retention that = (Retention) o;
205+
return Objects.equals(mode, that.mode)
206+
&& Objects.equals(retainUntilTime, that.retainUntilTime);
207+
}
208+
209+
@Override
210+
public int hashCode() {
211+
return Objects.hash(mode, retainUntilTime);
212+
}
213+
214+
@Override
215+
public String toString() {
216+
return MoreObjects.toStringHelper(this)
217+
.add("mode", mode)
218+
.add("retainUntilTime", retainUntilTime)
219+
.toString();
220+
}
221+
222+
public static Builder newBuilder() {
223+
return new Builder();
224+
}
225+
226+
public Builder toBuilder() {
227+
return new Builder().setMode(this.mode).setRetainUntilTime(this.retainUntilTime);
228+
}
229+
230+
private Retention() {}
231+
232+
public Retention(Builder builder) {
233+
this.mode = builder.mode;
234+
this.retainUntilTime = builder.retainUntilTime;
235+
}
236+
237+
public static final class Builder {
238+
private Mode mode;
239+
private OffsetDateTime retainUntilTime;
240+
241+
/** Sets the retention policy's Mode. Can be Locked or Unlocked. */
242+
public Builder setMode(Mode mode) {
243+
this.mode = mode;
244+
return this;
245+
}
246+
247+
/** Sets what time this object will be retained until, if the mode is Locked. */
248+
public Builder setRetainUntilTime(OffsetDateTime retainUntilTime) {
249+
this.retainUntilTime = retainUntilTime;
250+
return this;
251+
}
252+
253+
public Retention build() {
254+
return new Retention(this);
255+
}
256+
}
257+
258+
public static final class Mode extends StringEnumValue {
259+
private static final long serialVersionUID = 1973143582659557184L;
260+
261+
private Mode(String constant) {
262+
super(constant);
263+
}
264+
265+
private static final ApiFunction<String, Mode> CONSTRUCTOR = Mode::new;
266+
267+
private static final StringEnumType<Mode> type =
268+
new StringEnumType<>(Mode.class, CONSTRUCTOR);
269+
270+
public static final Mode UNLOCKED = type.createAndRegister("Unlocked");
271+
272+
public static final Mode LOCKED = type.createAndRegister("Locked");
273+
274+
public static Mode valueOfStrict(String constant) {
275+
return type.valueOfStrict(constant);
276+
}
277+
278+
public static Mode valueOf(String constant) {
279+
return type.valueOf(constant);
280+
}
281+
282+
public static Mode[] values() {
283+
return type.values();
284+
}
285+
}
286+
}
287+
171288
/** Builder for {@code BlobInfo}. */
172289
public abstract static class Builder {
173290

@@ -408,6 +525,8 @@ Builder setRetentionExpirationTimeOffsetDateTime(OffsetDateTime retentionExpirat
408525
return setRetentionExpirationTime(millisOffsetDateTimeCodec.decode(retentionExpirationTime));
409526
}
410527

528+
public abstract Builder setRetention(Retention retention);
529+
411530
/** Creates a {@code BlobInfo} object. */
412531
public abstract BlobInfo build();
413532

@@ -506,6 +625,7 @@ static final class BuilderImpl extends Builder {
506625
private Boolean eventBasedHold;
507626
private Boolean temporaryHold;
508627
private OffsetDateTime retentionExpirationTime;
628+
private Retention retention;
509629
private final ImmutableSet.Builder<NamedField> modifiedFields = ImmutableSet.builder();
510630

511631
BuilderImpl(BlobId blobId) {
@@ -543,6 +663,7 @@ static final class BuilderImpl extends Builder {
543663
eventBasedHold = blobInfo.eventBasedHold;
544664
temporaryHold = blobInfo.temporaryHold;
545665
retentionExpirationTime = blobInfo.retentionExpirationTime;
666+
retention = blobInfo.retention;
546667
}
547668

548669
@Override
@@ -916,6 +1037,14 @@ Builder setRetentionExpirationTimeOffsetDateTime(OffsetDateTime retentionExpirat
9161037
return this;
9171038
}
9181039

1040+
@Override
1041+
public Builder setRetention(Retention retention) {
1042+
// todo: b/308194853
1043+
modifiedFields.add(BlobField.RETENTION);
1044+
this.retention = retention;
1045+
return this;
1046+
}
1047+
9191048
@Override
9201049
public BlobInfo build() {
9211050
checkNotNull(blobId);
@@ -1139,6 +1268,7 @@ Builder clearRetentionExpirationTime() {
11391268
eventBasedHold = builder.eventBasedHold;
11401269
temporaryHold = builder.temporaryHold;
11411270
retentionExpirationTime = builder.retentionExpirationTime;
1271+
retention = builder.retention;
11421272
modifiedFields = builder.modifiedFields.build();
11431273
}
11441274

@@ -1532,6 +1662,11 @@ public OffsetDateTime getRetentionExpirationTimeOffsetDateTime() {
15321662
return retentionExpirationTime;
15331663
}
15341664

1665+
/** Returns the object's Retention policy. */
1666+
public Retention getRetention() {
1667+
return retention;
1668+
}
1669+
15351670
/** Returns a builder for the current blob. */
15361671
public Builder toBuilder() {
15371672
return new BuilderImpl(this);
@@ -1581,6 +1716,7 @@ public int hashCode() {
15811716
kmsKeyName,
15821717
eventBasedHold,
15831718
temporaryHold,
1719+
retention,
15841720
retentionExpirationTime);
15851721
}
15861722

@@ -1622,7 +1758,8 @@ public boolean equals(Object o) {
16221758
&& Objects.equals(kmsKeyName, blobInfo.kmsKeyName)
16231759
&& Objects.equals(eventBasedHold, blobInfo.eventBasedHold)
16241760
&& Objects.equals(temporaryHold, blobInfo.temporaryHold)
1625-
&& Objects.equals(retentionExpirationTime, blobInfo.retentionExpirationTime);
1761+
&& Objects.equals(retentionExpirationTime, blobInfo.retentionExpirationTime)
1762+
&& Objects.equals(retention, blobInfo.retention);
16261763
}
16271764

16281765
ImmutableSet<NamedField> getModifiedFields() {

google-cloud-storage/src/main/java/com/google/cloud/storage/Bucket.java

+16
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,16 @@ public static BlobTargetOption userProject(@NonNull String userProject) {
272272
return new BlobTargetOption(UnifiedOpts.userProject(userProject));
273273
}
274274

275+
/**
276+
* Returns an option for overriding an Unlocked Retention policy. This must be set to true in
277+
* order to change a policy from Unlocked to Locked, to set it to null, or to reduce its
278+
* retainUntilTime attribute.
279+
*/
280+
@TransportCompatibility({Transport.HTTP})
281+
public static BlobTargetOption overrideUnlockedRetention(boolean overrideUnlockedRetention) {
282+
return new BlobTargetOption(UnifiedOpts.overrideUnlockedRetention(overrideUnlockedRetention));
283+
}
284+
275285
/**
276286
* Deduplicate any options which are the same parameter. The value which comes last in {@code
277287
* os} will be the value included in the return.
@@ -732,6 +742,12 @@ public Builder setCustomPlacementConfig(CustomPlacementConfig customPlacementCon
732742
return this;
733743
}
734744

745+
@Override
746+
Builder setObjectRetention(ObjectRetention objectRetention) {
747+
infoBuilder.setObjectRetention(objectRetention);
748+
return this;
749+
}
750+
735751
@Override
736752
public Bucket build() {
737753
return new Bucket(storage, infoBuilder);

0 commit comments

Comments
 (0)