diff --git a/api/src/main/java/io/minio/GetObjectRetentionArgs.java b/api/src/main/java/io/minio/GetObjectRetentionArgs.java index 53e29faab..6d020eb84 100644 --- a/api/src/main/java/io/minio/GetObjectRetentionArgs.java +++ b/api/src/main/java/io/minio/GetObjectRetentionArgs.java @@ -16,7 +16,7 @@ package io.minio; -/** Argument class of MinioClient.getDefaultRetention(). */ +/** Argument class of MinioClient.getObjectRetention(). */ public class GetObjectRetentionArgs extends ObjectArgs { public static Builder builder() { return new Builder(); diff --git a/api/src/main/java/io/minio/MinioClient.java b/api/src/main/java/io/minio/MinioClient.java index 1de92a873..d8815d92f 100755 --- a/api/src/main/java/io/minio/MinioClient.java +++ b/api/src/main/java/io/minio/MinioClient.java @@ -3811,7 +3811,7 @@ public ObjectLockConfiguration getDefaultRetention(String bucketName) * @param objectName Object name in the bucket. * @param versionId Version ID of the object. * @param config Object retention configuration. - * @param bypassGovernanceRetention Bypass Governance retention. + * @param bypassGovernanceMode Bypass Governance retention. * @throws ErrorResponseException thrown to indicate S3 service returned an error response. * @throws IllegalArgumentException throws to indicate invalid argument passed. * @throws InsufficientDataException thrown to indicate not enough data available in InputStream. @@ -3830,7 +3830,7 @@ public void setObjectRetention( String objectName, String versionId, Retention config, - boolean bypassGovernanceRetention) + boolean bypassGovernanceMode) throws ErrorResponseException, IllegalArgumentException, InsufficientDataException, InternalException, InvalidBucketNameException, InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException, XmlParserException { @@ -3841,7 +3841,7 @@ public void setObjectRetention( .object(objectName) .versionId(versionId) .config(config) - .bypassGovernanceRetention(bypassGovernanceRetention) + .bypassGovernanceMode(bypassGovernanceMode) .build()); } @@ -3849,9 +3849,15 @@ public void setObjectRetention( * Sets retention configuration to an object. * *
Example:{@code
-   * Retention retention =
-   *     new Retention(RetentionMode.COMPLIANCE, ZonedDateTime.now().plusYears(1));
-   * minioClient.setObjectRetention(SetObjectRetentionArgs args);
+   *  Retention retention = new Retention(
+   *       RetentionMode.COMPLIANCE, ZonedDateTime.now().plusYears(1));
+   *  minioClient.setObjectRetention(
+   *      SetObjectRetentionArgs.builder()
+   *          .bucket("my-bucketname")
+   *          .object("my-objectname")
+   *          .config(config)
+   *          .bypassGovernanceMode(true)
+   *          .build());
    * }
* * @param args {@link SetObjectRetentionArgs} object. @@ -3871,24 +3877,24 @@ public void setObjectRetention(SetObjectRetentionArgs args) throws ErrorResponseException, IllegalArgumentException, InsufficientDataException, InternalException, InvalidBucketNameException, InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException, XmlParserException { - if (args.config() == null) { - throw new IllegalArgumentException("null value is not allowed in config."); + if (args == null) { + throw new IllegalArgumentException("null arguments"); } Map queryParamMap = new HashMap<>(); queryParamMap.put("retention", ""); - if (args.versionId() != null && !args.versionId().isEmpty()) { + if (args.versionId() != null) { queryParamMap.put("versionId", args.versionId()); } Map headerMap = new HashMap<>(); - if (args.bypassGovernanceRetention()) { + if (args.bypassGovernanceMode()) { headerMap.put("x-amz-bypass-governance-retention", "True"); } Response response = - executePut(args.bucket(), args.objectName(), headerMap, queryParamMap, args.config(), 0); + executePut(args.bucket(), args.object(), headerMap, queryParamMap, args.config(), 0); response.body().close(); } @@ -3918,6 +3924,7 @@ public void setObjectRetention(SetObjectRetentionArgs args) * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws XmlParserException thrown to indicate XML parsing error. */ + @Deprecated public Retention getObjectRetention(String bucketName, String objectName, String versionId) throws ErrorResponseException, IllegalArgumentException, InsufficientDataException, InternalException, InvalidBucketNameException, InvalidKeyException, @@ -3935,7 +3942,11 @@ public Retention getObjectRetention(String bucketName, String objectName, String * *
Example:{@code
    * Retention retention =
-   *     minioClient.getObjectRetention(GetObjectRetentionArgs args);
+   *     minioClient.getObjectRetention(GetObjectRetentionArgs.builder()
+   *        .bucket(bucketName)
+   *        .object(objectName)
+   *        .versionId(versionId)
+   *        .build()););
    * System.out.println(
    *     "mode: " + retention.mode() + "until: " + retention.retainUntilDate());
    * }
@@ -3958,14 +3969,18 @@ public Retention getObjectRetention(GetObjectRetentionArgs args) throws ErrorResponseException, IllegalArgumentException, InsufficientDataException, InternalException, InvalidBucketNameException, InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException, XmlParserException { + if (args == null) { + throw new IllegalArgumentException("null arguments"); + } + Map queryParamMap = new HashMap<>(); queryParamMap.put("retention", ""); - if (args.versionId() != null && !args.versionId().isEmpty()) { + if (args.versionId() != null) { queryParamMap.put("versionId", args.versionId()); } - try (Response response = executeGet(args.bucket(), args.objectName(), null, queryParamMap)) { + try (Response response = executeGet(args.bucket(), args.object(), null, queryParamMap)) { Retention retention = Xml.unmarshal(Retention.class, response.body().charStream()); return retention; } catch (ErrorResponseException e) { diff --git a/api/src/main/java/io/minio/SetObjectRetentionArgs.java b/api/src/main/java/io/minio/SetObjectRetentionArgs.java index b917c80d8..a3e669bed 100644 --- a/api/src/main/java/io/minio/SetObjectRetentionArgs.java +++ b/api/src/main/java/io/minio/SetObjectRetentionArgs.java @@ -18,16 +18,17 @@ import io.minio.messages.Retention; +/** Argument class of MinioClient.setObjectRetention(). */ public class SetObjectRetentionArgs extends ObjectArgs { private Retention config; - private boolean bypassGovernanceRetention; + private boolean bypassGovernanceMode; public Retention config() { return config; } - public boolean bypassGovernanceRetention() { - return bypassGovernanceRetention; + public boolean bypassGovernanceMode() { + return bypassGovernanceMode; } public static Builder builder() { @@ -37,16 +38,12 @@ public static Builder builder() { /** Argument builder of {@link SetObjectRetentionArgs}. */ public static final class Builder extends ObjectArgs.Builder { public Builder config(Retention config) { - if (config == null) { - throw new IllegalArgumentException("null object retention configuration"); - } - operations.add(args -> args.config = config); return this; } - public Builder bypassGovernanceRetention(boolean bypassGovernanceRetention) { - operations.add(args -> args.bypassGovernanceRetention = bypassGovernanceRetention); + public Builder bypassGovernanceMode(boolean bypassGovernanceMode) { + operations.add(args -> args.bypassGovernanceMode = bypassGovernanceMode); return this; } } diff --git a/docs/API.md b/docs/API.md index 4108de325..605ba314a 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1064,9 +1064,9 @@ Gets retention configuration of an object. __Parameters__ -| Parameter | Type | Description | -|:---------------|:---------------------------|:---------------------------| -| ``args`` | _[GetObjectRetentionArgs]_ | Object retention arguments | +| Parameter | Type | Description | +|:---------------|:---------------------------|:--------------| +| ``args`` | _[GetObjectRetentionArgs]_ | Arguments. | | Returns | |:------------------------------------------------| @@ -1074,16 +1074,8 @@ Gets retention configuration of an object. __Example__ ```java -// Object without version -Retention retention = - minioClient.getObjectRetention( - GetObjectRetentionArgs.builder() - .bucket("my-bucketname") - .object("my-objectname") - .build()); -System.out.println("mode: " + retention.mode() + "until: " + retention.retainUntilDate()); -// Object with version +// Object with version id. Retention retention = minioClient.getObjectRetention( GetObjectRetentionArgs.builder() @@ -1473,9 +1465,9 @@ Sets retention configuration to an object. __Parameters__ -| Parameter | Type | Description | -|:-----------------|:---------------------------|:-----------------------------------| -| ``args`` | _[SetObjectRetentionArgs]_ | Arguments to set object retention. | +| Parameter | Type | Description | +|:-----------------|:---------------------------|:-------------| +| ``args`` | _[SetObjectRetentionArgs]_ | Arguments. | __Example__ ```java @@ -1485,7 +1477,7 @@ minioClient.setObjectRetention( .bucket("my-bucketname") .object("my-objectname") .config(retention) - .bypassGovernanceRetention(true) + .bypassGovernanceMode(true) .build()); ``` diff --git a/examples/GetObjectRetention.java b/examples/GetObjectRetention.java new file mode 100644 index 000000000..2f8b14456 --- /dev/null +++ b/examples/GetObjectRetention.java @@ -0,0 +1,52 @@ +/* + * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2020 MinIO, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import io.minio.GetObjectRetentionArgs; +import io.minio.MinioClient; +import io.minio.errors.MinioException; +import io.minio.messages.Retention; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +public class GetObjectRetention { + /** MinioClient.getObjectRetention() example. */ + public static void main(String[] args) + throws IOException, NoSuchAlgorithmException, InvalidKeyException, IllegalArgumentException { + try { + + /* play.min.io for test and development. */ + MinioClient minioClient = + new MinioClient( + "https://play.min.io", + "Q3AM3UQ867SPQQA43P2F", + "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG"); + + // Get object lock retention + Retention retention = + minioClient.getObjectRetention( + GetObjectRetentionArgs.builder() + .bucket("my-bucketname") + .object("my-objectname") + .build()); + + System.out.println("Mode: " + retention.mode()); + System.out.println("Retainuntil Date: " + retention.retainUntilDate()); + } catch (MinioException e) { + System.out.println("Error occurred: " + e); + } + } +} diff --git a/examples/GetObjectRetentionConfig.java b/examples/SetObjectRetention.java similarity index 51% rename from examples/GetObjectRetentionConfig.java rename to examples/SetObjectRetention.java index bd829049a..6dad6919a 100644 --- a/examples/GetObjectRetentionConfig.java +++ b/examples/SetObjectRetention.java @@ -15,34 +15,20 @@ */ import io.minio.GetObjectRetentionArgs; -import io.minio.MakeBucketArgs; import io.minio.MinioClient; -import io.minio.PutObjectOptions; import io.minio.SetObjectRetentionArgs; -import io.minio.errors.ErrorResponseException; -import io.minio.errors.InsufficientDataException; -import io.minio.errors.InternalException; -import io.minio.errors.InvalidBucketNameException; -import io.minio.errors.InvalidEndpointException; -import io.minio.errors.InvalidPortException; -import io.minio.errors.InvalidResponseException; import io.minio.errors.MinioException; -import io.minio.errors.RegionConflictException; import io.minio.messages.Retention; import io.minio.messages.RetentionMode; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.time.ZonedDateTime; -public class GetObjectRetentionConfig { - /** MinioClient.getObjectRetention() example. */ +public class SetObjectRetention { + /** MinioClient.setObjectRetention() example. */ public static void main(String[] args) - throws IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, - InsufficientDataException, InternalException, ErrorResponseException, - InvalidBucketNameException, InvalidPortException, InvalidEndpointException, - RegionConflictException, IllegalArgumentException { + throws IOException, NoSuchAlgorithmException, InvalidKeyException, IllegalArgumentException { try { /* play.min.io for test and development. */ @@ -52,37 +38,6 @@ public static void main(String[] args) "Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG"); - // Create bucket if it doesn't exist. - boolean found = minioClient.bucketExists("my-bucketname"); - if (found) { - System.out.println("my-bucketname already exists"); - } else { - // Create bucket 'my-bucketname' with object lock functionality enabled - minioClient.makeBucket( - MakeBucketArgs.builder().bucket("my-bucketname").objectLock(true).build()); - System.out.println( - "my-bucketname is created successfully with object lock functionality enabled."); - } - - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < 100; i++) { - builder.append( - "Sphinx of black quartz, judge my vow: Used by Adobe InDesign to display font samples. "); - builder.append("(29 letters)\n"); - builder.append( - "Jackdaws love my big sphinx of quartz: Similarly, used by Windows XP for some fonts. "); - builder.append("---\n"); - } - - // Create a InputStream for object upload. - ByteArrayInputStream bais = new ByteArrayInputStream(builder.toString().getBytes("UTF-8")); - - // Create object 'my-objectname' in 'my-bucketname' with content from the input stream. - minioClient.putObject( - "my-bucketname", "my-objectname", bais, new PutObjectOptions(bais.available(), -1)); - bais.close(); - System.out.println("my-objectname is uploaded successfully"); - // Declaring config with Retention mode as Compliance and // retain until one year to current date. ZonedDateTime retentionUntil = ZonedDateTime.now().plusYears(1); @@ -94,7 +49,7 @@ public static void main(String[] args) .bucket("my-bucketname") .object("my-objectname") .config(config) - .bypassGovernanceRetention(true) + .bypassGovernanceMode(true) .build()); // Get object lock retention diff --git a/examples/SetObjectRetentionConfig.java b/examples/SetObjectRetentionConfig.java deleted file mode 100644 index 1507071ef..000000000 --- a/examples/SetObjectRetentionConfig.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2020 MinIO, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import io.minio.MakeBucketArgs; -import io.minio.MinioClient; -import io.minio.PutObjectOptions; -import io.minio.SetObjectRetentionArgs; -import io.minio.errors.ErrorResponseException; -import io.minio.errors.InsufficientDataException; -import io.minio.errors.InternalException; -import io.minio.errors.InvalidBucketNameException; -import io.minio.errors.InvalidEndpointException; -import io.minio.errors.InvalidPortException; -import io.minio.errors.InvalidResponseException; -import io.minio.errors.MinioException; -import io.minio.errors.RegionConflictException; -import io.minio.messages.Retention; -import io.minio.messages.RetentionMode; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.time.ZonedDateTime; - -public class SetObjectRetentionConfig { - /** MinioClient.setObjectRetention() example. */ - public static void main(String[] args) - throws IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, - InsufficientDataException, InternalException, ErrorResponseException, - InvalidBucketNameException, InvalidPortException, InvalidEndpointException, - RegionConflictException, IllegalArgumentException { - try { - - /* play.min.io for test and development. */ - MinioClient minioClient = - new MinioClient( - "https://play.min.io", - "Q3AM3UQ867SPQQA43P2F", - "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG"); - - // Create bucket if it doesn't exist. - boolean found = minioClient.bucketExists("my-bucketname"); - if (found) { - System.out.println("my-bucketname already exists"); - } else { - // Create bucket 'my-bucketname' with object lock functionality enabled - minioClient.makeBucket( - MakeBucketArgs.builder().bucket("my-bucketname").objectLock(true).build()); - System.out.println( - "my-bucketname is created successfully with object lock functionality enabled."); - } - - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < 100; i++) { - builder.append( - "Sphinx of black quartz, judge my vow: Used by Adobe InDesign to display font samples. "); - builder.append("(29 letters)\n"); - builder.append( - "Jackdaws love my big sphinx of quartz: Similarly, used by Windows XP for some fonts. "); - builder.append("---\n"); - } - - // Create a InputStream for object upload. - ByteArrayInputStream bais = new ByteArrayInputStream(builder.toString().getBytes("UTF-8")); - - // Create object 'my-objectname' in 'my-bucketname' with content from the input stream. - minioClient.putObject( - "my-bucketname", "my-objectname", bais, new PutObjectOptions(bais.available(), -1)); - bais.close(); - System.out.println("my-objectname is uploaded successfully"); - - // Declaring config with Retention mode as Compliance and - // retain until one year to current date. - ZonedDateTime retentionUntil = ZonedDateTime.now().plusYears(1); - Retention config = new Retention(RetentionMode.COMPLIANCE, retentionUntil); - - // Set object lock configuration - minioClient.setObjectRetention( - SetObjectRetentionArgs.builder() - .bucket("my-bucketname") - .object("my-objectname") - .config(config) - .bypassGovernanceRetention(true) - .build()); - - // Get object lock retention - Retention retention = minioClient.getObjectRetention("my-bucketname", "my-objectname", ""); - - System.out.println("Mode: " + retention.mode()); - System.out.println("Retainuntil Date: " + retention.retainUntilDate()); - } catch (MinioException e) { - System.out.println("Error occurred: " + e); - } - } -} diff --git a/functional/FunctionalTest.java b/functional/FunctionalTest.java index b61f22895..12f76caa0 100644 --- a/functional/FunctionalTest.java +++ b/functional/FunctionalTest.java @@ -25,6 +25,7 @@ import io.minio.DisableVersioningArgs; import io.minio.EnableVersioningArgs; import io.minio.ErrorCode; +import io.minio.GetObjectRetentionArgs; import io.minio.ListObjectsArgs; import io.minio.MakeBucketArgs; import io.minio.MinioClient; @@ -36,6 +37,7 @@ import io.minio.Result; import io.minio.SelectResponseStream; import io.minio.ServerSideEncryption; +import io.minio.SetObjectRetentionArgs; import io.minio.StatObjectArgs; import io.minio.Time; import io.minio.errors.ErrorResponseException; @@ -51,6 +53,7 @@ import io.minio.messages.ObjectLockConfiguration; import io.minio.messages.OutputSerialization; import io.minio.messages.QuoteFields; +import io.minio.messages.Retention; import io.minio.messages.RetentionDurationDays; import io.minio.messages.RetentionDurationYears; import io.minio.messages.RetentionMode; @@ -3761,6 +3764,309 @@ public static void getDefaultRetention_test() throws Exception { } } + /** Test: setObjectRetention(SetObjectRetentionArgs args). */ + public static void setObjectRetention_test() throws Exception { + if (!mintEnv) { + System.out.println("Test: setObjectRetention(SetObjectRetentionArgs args)"); + } + + long startTime = System.currentTimeMillis(); + String bucketName = getRandomName(); + String objectName = getRandomName(); + try { + client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).objectLock(true).build()); + try { + ZonedDateTime retentionUntil = ZonedDateTime.now().plusDays(1); + Retention expectedConfig = new Retention(RetentionMode.GOVERNANCE, retentionUntil); + + try (final InputStream is = new ContentInputStream(1 * KB)) { + PutObjectOptions options = new PutObjectOptions(1 * KB, -1); + options.setContentType(customContentType); + client.putObject(bucketName, objectName, is, options); + } + + client.setObjectRetention( + SetObjectRetentionArgs.builder() + .bucket(bucketName) + .object(objectName) + .config(expectedConfig) + .build()); + // Set empty object lock configuration by setting bypassGovernanceMode as true + Retention emptyConfig = new Retention(); + client.setObjectRetention( + SetObjectRetentionArgs.builder() + .bucket(bucketName) + .object(objectName) + .config(emptyConfig) + .bypassGovernanceMode(true) + .build()); + + } finally { + client.removeObject( + RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build()); + client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); + } + + mintSuccessLog("setObjectRetention(SetObjectRetentionArgs args)", null, startTime); + + } catch (Exception e) { + ErrorResponse errorResponse = null; + if (e instanceof ErrorResponseException) { + ErrorResponseException exp = (ErrorResponseException) e; + errorResponse = exp.errorResponse(); + } + + // Ignore NotImplemented error + if (errorResponse != null && errorResponse.errorCode() == ErrorCode.NOT_IMPLEMENTED) { + mintIgnoredLog("setObjectRetention(SetObjectRetentionArgs args)", null, startTime); + } else { + mintFailedLog( + "setObjectRetention(SetObjectRetentionArgs args)", + null, + startTime, + null, + e.toString() + " >>> " + Arrays.toString(e.getStackTrace())); + throw e; + } + } + } + + /** Test: getObjectRetention(GetObjectRetentionArgs args). */ + public static void getObjectRetention_test1() throws Exception { + if (!mintEnv) { + System.out.println("Test: getObjectRetention(GetObjectRetentionArgs args)"); + } + + long startTime = System.currentTimeMillis(); + String bucketName = getRandomName(); + String objectName = getRandomName(); + try { + client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).objectLock(true).build()); + try { + try (final InputStream is = new ContentInputStream(1 * KB)) { + PutObjectOptions options = new PutObjectOptions(1 * KB, -1); + options.setContentType(customContentType); + client.putObject(bucketName, objectName, is, options); + } + + ZonedDateTime retentionUntil = ZonedDateTime.now().plusDays(3); + Retention expectedConfig = new Retention(RetentionMode.GOVERNANCE, retentionUntil); + client.setObjectRetention( + SetObjectRetentionArgs.builder() + .bucket(bucketName) + .object(objectName) + .config(expectedConfig) + .build()); + + Retention config = + client.getObjectRetention( + GetObjectRetentionArgs.builder().bucket(bucketName).object(objectName).build()); + + if ((!(config + .retainUntilDate() + .toString() + .substring(0, config.retainUntilDate().toString().indexOf("T")) + .equals( + expectedConfig + .retainUntilDate() + .toString() + .substring(0, expectedConfig.retainUntilDate().toString().indexOf("T"))))) + || (config.mode() != expectedConfig.mode())) { + throw new Exception( + "[FAILED] Expected: expected duration : " + + expectedConfig.retainUntilDate() + + ", got: " + + config.retainUntilDate() + + " expected mode :" + + expectedConfig.mode() + + ", got: " + + config.mode()); + } + + // Set empty object lock configuration by setting bypassGovernanceMode as true + Retention emptyConfig = new Retention(); + client.setObjectRetention( + SetObjectRetentionArgs.builder() + .bucket(bucketName) + .object(objectName) + .config(emptyConfig) + .bypassGovernanceMode(true) + .build()); + + } finally { + client.removeObject( + RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build()); + client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); + } + + mintSuccessLog("getObjectRetention(GetObjectRetentionArgs args)", null, startTime); + + } catch (Exception e) { + ErrorResponse errorResponse = null; + if (e instanceof ErrorResponseException) { + ErrorResponseException exp = (ErrorResponseException) e; + errorResponse = exp.errorResponse(); + } + + // Ignore NotImplemented error + if (errorResponse != null && errorResponse.errorCode() == ErrorCode.NOT_IMPLEMENTED) { + mintIgnoredLog("getObjectRetention(GetObjectRetentionArgs args)", null, startTime); + } else { + mintFailedLog( + "getObjectRetention(GetObjectRetentionArgs args)", + null, + startTime, + null, + e.toString() + " >>> " + Arrays.toString(e.getStackTrace())); + throw e; + } + } + } + + /** Test: getObjectRetention(GetObjectRetentionArgs args). */ + public static void getObjectRetention_test2() throws Exception { + if (!mintEnv) { + System.out.println( + "Test: with shortened retention period: getObjectRetention(GetObjectRetentionArgs args)"); + } + + long startTime = System.currentTimeMillis(); + String bucketName = getRandomName(); + String objectName = getRandomName(); + try { + client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).objectLock(true).build()); + try { + try (final InputStream is = new ContentInputStream(1 * KB)) { + PutObjectOptions options = new PutObjectOptions(1 * KB, -1); + options.setContentType(customContentType); + client.putObject(bucketName, objectName, is, options); + } + + ZonedDateTime retentionUntil = ZonedDateTime.now().plusDays(3); + Retention expectedConfig = new Retention(RetentionMode.GOVERNANCE, retentionUntil); + client.setObjectRetention( + SetObjectRetentionArgs.builder() + .bucket(bucketName) + .object(objectName) + .config(expectedConfig) + .build()); + + Retention config = + client.getObjectRetention( + GetObjectRetentionArgs.builder().bucket(bucketName).object(objectName).build()); + + if ((!(config + .retainUntilDate() + .toString() + .substring(0, config.retainUntilDate().toString().indexOf("T")) + .equals( + expectedConfig + .retainUntilDate() + .toString() + .substring(0, expectedConfig.retainUntilDate().toString().indexOf("T"))))) + || (config.mode() != expectedConfig.mode())) { + throw new Exception( + "[FAILED] Expected: expected duration : " + + expectedConfig.retainUntilDate() + + ", got: " + + config.retainUntilDate() + + " expected mode :" + + expectedConfig.mode() + + ", got: " + + config.mode()); + } + + // You can perform operations on object versions that are locked in governance mode as if + // they were unprotected if you have the s3:bypassGovernanceMode permission. These + // operations include deleting an object version, shortening the retention period, or + // removing the Object Lock by placing a new lock with empty parameters. + ZonedDateTime shortenedRetentionUntil = ZonedDateTime.now().plusDays(1); + Retention expectedConfigWithShortenedPeriod = + new Retention(RetentionMode.GOVERNANCE, shortenedRetentionUntil); + client.setObjectRetention( + SetObjectRetentionArgs.builder() + .bucket(bucketName) + .object(objectName) + .config(expectedConfigWithShortenedPeriod) + .bypassGovernanceMode(true) + .build()); + + Retention updatedConfig = + client.getObjectRetention( + GetObjectRetentionArgs.builder().bucket(bucketName).object(objectName).build()); + + if ((!(updatedConfig + .retainUntilDate() + .toString() + .substring(0, updatedConfig.retainUntilDate().toString().indexOf("T")) + .equals( + expectedConfigWithShortenedPeriod + .retainUntilDate() + .toString() + .substring( + 0, + expectedConfigWithShortenedPeriod + .retainUntilDate() + .toString() + .indexOf("T"))))) + || (updatedConfig.mode() != expectedConfigWithShortenedPeriod.mode())) { + throw new Exception( + "[FAILED] Expected: expected duration : " + + expectedConfigWithShortenedPeriod.retainUntilDate() + + ", got: " + + updatedConfig.retainUntilDate() + + " expected mode :" + + expectedConfigWithShortenedPeriod.mode() + + ", got: " + + updatedConfig.mode()); + } + + // Set empty object lock configuration by setting bypassGovernanceMode as true + Retention emptyConfig = new Retention(); + client.setObjectRetention( + SetObjectRetentionArgs.builder() + .bucket(bucketName) + .object(objectName) + .config(emptyConfig) + .bypassGovernanceMode(true) + .build()); + + } finally { + client.removeObject( + RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build()); + client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); + } + + mintSuccessLog( + "getObjectRetention(GetObjectRetentionArgs args)", + "shortening the retention period", + startTime); + + } catch (Exception e) { + ErrorResponse errorResponse = null; + if (e instanceof ErrorResponseException) { + ErrorResponseException exp = (ErrorResponseException) e; + errorResponse = exp.errorResponse(); + } + + // Ignore NotImplemented error + if (errorResponse != null && errorResponse.errorCode() == ErrorCode.NOT_IMPLEMENTED) { + mintIgnoredLog( + "getObjectRetention(GetObjectRetentionArgs args)", + "shortening the retention period", + startTime); + } else { + mintFailedLog( + "getObjectRetention(GetObjectRetentionArgs args)", + "shortening the retention period", + startTime, + null, + e.toString() + " >>> " + Arrays.toString(e.getStackTrace())); + throw e; + } + } + } + /** Test: getBucketPolicy(String bucketName). */ public static void getBucketPolicy_test1() throws Exception { if (!mintEnv) { @@ -4273,6 +4579,10 @@ public static void runTests() throws Exception { setup(); + setObjectRetention_test(); + getObjectRetention_test1(); + getObjectRetention_test2(); + putObject_test1(); putObject_test2(); putObject_test3(); @@ -4341,6 +4651,10 @@ public static void runTests() throws Exception { setDefaultRetention_test(); getDefaultRetention_test(); + setObjectRetention_test(); + getObjectRetention_test1(); + getObjectRetention_test2(); + selectObjectContent_test1(); // SSE_C tests will only work over TLS connection