diff --git a/api/src/main/java/io/minio/ListenBucketNotificationArgs.java b/api/src/main/java/io/minio/ListenBucketNotificationArgs.java new file mode 100644 index 000000000..ca71da0d3 --- /dev/null +++ b/api/src/main/java/io/minio/ListenBucketNotificationArgs.java @@ -0,0 +1,74 @@ +/* + * 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 + * + * 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 io.minio; + +import java.util.Arrays; + +/** Argument class of MinioClient.ListenBucketNotification(). */ +public class ListenBucketNotificationArgs extends BucketArgs { + private String prefix; + private String suffix; + private String[] events = null; + + public String prefix() { + return prefix; + } + + public String suffix() { + return suffix; + } + + public String[] events() { + return Arrays.copyOf(events, events.length); + } + + public static Builder builder() { + return new Builder(); + } + + /** Argument builder of {@link ListenBucketNotificationArgs}. */ + public static final class Builder + extends BucketArgs.Builder { + private void validateEvents(String[] events) { + if (events == null) { + throw new IllegalArgumentException("null events"); + } + } + + protected void validate(ListenBucketNotificationArgs args) { + super.validate(args); + validateEvents(args.events); + } + + public Builder prefix(String prefix) { + operations.add(args -> args.prefix = prefix); + return this; + } + + public Builder suffix(String suffix) { + operations.add(args -> args.suffix = suffix); + return this; + } + + public Builder events(String[] events) { + validateEvents(events); + final String[] eventsCopy = Arrays.copyOf(events, events.length); + operations.add(args -> args.events = eventsCopy); + return this; + } + } +} diff --git a/api/src/main/java/io/minio/MinioClient.java b/api/src/main/java/io/minio/MinioClient.java index a5bfd6abb..cb07d4655 100755 --- a/api/src/main/java/io/minio/MinioClient.java +++ b/api/src/main/java/io/minio/MinioClient.java @@ -1407,7 +1407,7 @@ private String getRegion(String bucketName) throws ErrorResponseException, IllegalArgumentException, InsufficientDataException, InternalException, InvalidBucketNameException, InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException, ServerException, - ServerException, XmlParserException { + XmlParserException { if (this.region != null && !this.region.equals("")) { return this.region; } @@ -1629,7 +1629,7 @@ private Response executePut( * @throws IOException thrown to indicate I/O error on S3 operation. * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws XmlParserException thrown to indicate XML parsing error. - * @see ObjectStat + * @deprecated use {@link #statObject(StatObjectArgs)} */ @Deprecated public ObjectStat statObject(String bucketName, String objectName) @@ -1663,7 +1663,7 @@ public ObjectStat statObject(String bucketName, String objectName) * @throws IOException thrown to indicate I/O error on S3 operation. * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws XmlParserException thrown to indicate XML parsing error. - * @see ObjectStat + * @deprecated use {@link #statObject(StatObjectArgs)} */ @Deprecated public ObjectStat statObject( @@ -2912,6 +2912,7 @@ public Map presignedPostPolicy(PostPolicy policy) * @throws IOException thrown to indicate I/O error on S3 operation. * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws XmlParserException thrown to indicate XML parsing error. + * @deprecated use {@link #removeObject(RemoveObjectArgs)} */ @Deprecated public void removeObject(String bucketName, String objectName) @@ -3639,6 +3640,7 @@ public boolean bucketExists(BucketExistsArgs args) * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws RegionConflictException thrown to indicate passed region conflict with default region. * @throws XmlParserException thrown to indicate XML parsing error. + * @deprecated use {@link #makeBucket(MakeBucketArgs)} */ @Deprecated public void makeBucket(String bucketName) @@ -3670,6 +3672,7 @@ public void makeBucket(String bucketName) * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws RegionConflictException thrown to indicate passed region conflict with default region. * @throws XmlParserException thrown to indicate XML parsing error. + * @deprecated use {@link #makeBucket(MakeBucketArgs)} */ @Deprecated public void makeBucket(String bucketName, String region) @@ -3702,6 +3705,7 @@ public void makeBucket(String bucketName, String region) * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws RegionConflictException thrown to indicate passed region conflict with default region. * @throws XmlParserException thrown to indicate XML parsing error. + * @deprecated use {@link #makeBucket(MakeBucketArgs)} */ @Deprecated public void makeBucket(String bucketName, String region, boolean objectLock) @@ -4066,6 +4070,7 @@ public ObjectLockConfiguration getDefaultRetention(String bucketName) * @throws IOException thrown to indicate I/O error on S3 operation. * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws XmlParserException thrown to indicate XML parsing error. + * @deprecated use {@link #setObjectRetention(SetObjectRetentionArgs)} */ @Deprecated public void setObjectRetention( @@ -4166,6 +4171,7 @@ public void setObjectRetention(SetObjectRetentionArgs args) * @throws IOException thrown to indicate I/O error on S3 operation. * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws XmlParserException thrown to indicate XML parsing error. + * @deprecated use {@link #getObjectRetention(GetObjectRetentionArgs)} */ @Deprecated public Retention getObjectRetention(String bucketName, String objectName, String versionId) @@ -4516,6 +4522,7 @@ public boolean isObjectLegalHoldEnabled(IsObjectLegalHoldEnabledArgs args) * @throws IOException thrown to indicate I/O error on S3 operation. * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws XmlParserException thrown to indicate XML parsing error. + * @deprecated use {@link #removeBucket(RemoveBucketArgs)} */ @Deprecated public void removeBucket(String bucketName) @@ -5026,6 +5033,7 @@ public void deleteBucketPolicy(DeleteBucketPolicyArgs args) * @throws IOException thrown to indicate I/O error on S3 operation. * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws XmlParserException thrown to indicate XML parsing error. + * @deprecated use {@link #setBucketLifeCycle(SetBucketLifeCycleArgs)} */ @Deprecated public void setBucketLifeCycle(String bucketName, String lifeCycle) @@ -5102,6 +5110,7 @@ public void setBucketLifeCycle(SetBucketLifeCycleArgs args) * @throws IOException thrown to indicate I/O error on S3 operation. * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws XmlParserException thrown to indicate XML parsing error. + * @deprecated use {@link #deleteBucketLifeCycle(DeleteBucketLifeCycleArgs)} */ @Deprecated public void deleteBucketLifeCycle(String bucketName) @@ -5165,6 +5174,7 @@ public void deleteBucketLifeCycle(DeleteBucketLifeCycleArgs args) * @throws IOException thrown to indicate I/O error on S3 operation. * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. * @throws XmlParserException thrown to indicate XML parsing error. + * @deprecated use {@link #getBucketLifeCycle(GetBucketLifeCycleArgs)} */ @Deprecated public String getBucketLifeCycle(String bucketName) @@ -5720,7 +5730,7 @@ public void removeIncompleteUpload(String bucketName, String objectName) *
Example:{@code
    * String[] events = {"s3:ObjectCreated:*", "s3:ObjectAccessed:*"};
    * try (CloseableIterator> ci =
-   *     minioClient.listenBucketNotification("bcketName", "", "", events)) {
+   *     minioClient.listenBucketNotification("bucketName", "", "", events)) {
    *   while (ci.hasNext()) {
    *     NotificationRecords records = ci.next().get();
    *     for (Event event : records.events()) {
@@ -5749,22 +5759,81 @@ public void removeIncompleteUpload(String bucketName, String objectName)
    * @throws IOException thrown to indicate I/O error on S3 operation.
    * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library.
    * @throws XmlParserException thrown to indicate XML parsing error.
+   * @deprecated use {@link #listenBucketNotification(ListenBucketNotificationArgs)}
    */
+  @Deprecated
   public CloseableIterator> listenBucketNotification(
       String bucketName, String prefix, String suffix, String[] events)
       throws ErrorResponseException, IllegalArgumentException, InsufficientDataException,
           InternalException, InvalidBucketNameException, InvalidKeyException,
           InvalidResponseException, IOException, NoSuchAlgorithmException, ServerException,
           XmlParserException {
+    return listenBucketNotification(
+        ListenBucketNotificationArgs.builder()
+            .bucket(bucketName)
+            .prefix(prefix)
+            .suffix(suffix)
+            .events(events)
+            .build());
+  }
+
+  /**
+   * Listens events of object prefix and suffix of a bucket. The returned closable iterator is
+   * lazily evaluated hence its required to iterate to get new records and must be used with
+   * try-with-resource to release underneath network resources.
+   *
+   * 
Example:{@code
+   * String[] events = {"s3:ObjectCreated:*", "s3:ObjectAccessed:*"};
+   * try (CloseableIterator> ci =
+   *     minioClient.listenBucketNotification(
+   *         ListenBucketNotificationArgs.builder()
+   *             .bucket("bucketName")
+   *             .prefix("")
+   *             .suffix("")
+   *             .events(events)
+   *             .build())) {
+   *   while (ci.hasNext()) {
+   *     NotificationRecords records = ci.next().get();
+   *     for (Event event : records.events()) {
+   *       System.out.println("Event " + event.eventType() + " occurred at "
+   *           + event.eventTime() + " for " + event.bucketName() + "/"
+   *           + event.objectName());
+   *     }
+   *   }
+   * }
+   * }
+ * + * @param args {@link ListenBucketNotificationArgs} object. + * @return CloseableIterator<Result<NotificationRecords>> - Lazy closable iterator + * contains event records. + * @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. + * @throws InternalException thrown to indicate internal library error. + * @throws InvalidBucketNameException thrown to indicate invalid bucket name passed. + * @throws InvalidKeyException thrown to indicate missing of HMAC SHA-256 library. + * @throws InvalidResponseException thrown to indicate S3 service returned invalid or no error + * response. + * @throws IOException thrown to indicate I/O error on S3 operation. + * @throws NoSuchAlgorithmException thrown to indicate missing of MD5 or SHA-256 digest library. + * @throws XmlParserException thrown to indicate XML parsing error. + */ + public CloseableIterator> listenBucketNotification( + ListenBucketNotificationArgs args) + throws ErrorResponseException, IllegalArgumentException, InsufficientDataException, + InternalException, InvalidBucketNameException, InvalidKeyException, + InvalidResponseException, IOException, NoSuchAlgorithmException, ServerException, + XmlParserException { + checkArgs(args); + Multimap queryParamMap = HashMultimap.create(); - queryParamMap.put("prefix", prefix); - queryParamMap.put("suffix", suffix); - for (String event : events) { + queryParamMap.put("prefix", args.prefix()); + queryParamMap.put("suffix", args.suffix()); + for (String event : args.events()) { queryParamMap.put("events", event); } - Response response = executeGet(bucketName, "", queryParamMap); - + Response response = executeGet(args.bucket(), "", queryParamMap); NotificationResultRecords result = new NotificationResultRecords(response); return result.closeableIterator(); } diff --git a/docs/API.md b/docs/API.md index f2ddbe63d..60609e779 100644 --- a/docs/API.md +++ b/docs/API.md @@ -570,18 +570,15 @@ for (Bucket bucket : bucketList) { ``` -### listenBucketNotification(String bucketName, String prefix, String suffix, String[] events) -`public CloseableIterator> listenBucketNotification(String bucketName, String prefix, String suffix, String[] events)` _[[Javadoc]](http://minio.github.io/minio-java/io/minio/MinioClient.html#listenBucketNotification-java.lang.String-java.lang.String-java.lang.String-java.lang.String:A-)_ +### listenBucketNotification(ListenBucketNotificationArgs args) +`public CloseableIterator> listenBucketNotification(ListenBucketNotificationArgs args)` _[[Javadoc]](http://minio.github.io/minio-java/io/minio/MinioClient.html#listenBucketNotification-io.minio.ListenBucketNotificationArgs-)_ Listens events of object prefix and suffix of a bucket. The returned closable iterator is lazily evaluated hence its required to iterate to get new records and must be used with try-with-resource to release underneath network resources. __Parameters__ -| Parameter | Type | Description | -|:---------------|:-----------|:--------------------------------------------| -| ``bucketName`` | _String_ | Name of the bucket. | -| ``prefix`` | _String_ | Listen events of object starts with prefix. | -| ``suffix`` | _String_ | Listen events of object ends with suffix. | -| ``events`` | _String[]_ | Events to listen. | +| Parameter | Type | Description | +|:----------|:---------------------------------|:------------| +| ``args`` | _[ListenBucketNotificationArgs]_ | Arguments. | | Returns | |:--------------------------------------------------------------------------------------------------------| @@ -590,8 +587,14 @@ __Parameters__ __Example__ ```java String[] events = {"s3:ObjectCreated:*", "s3:ObjectAccessed:*"}; -try (CloseableIterator> ci = - minioClient.listenBucketNotification("bcketName", "", "", events)) { +try (CloseableIterator> ci = + minioClient.listenBucketNotification( + ListenBucketNotificationArgs.builder() + .bucket("bucketName") + .prefix("") + .suffix("") + .events(events) + .build())) { while (ci.hasNext()) { NotificationRecords records = ci.next().get(); for (Event event : records.events()) { @@ -1788,4 +1791,5 @@ ObjectStat objectStat = [BucketExistsArgs]: http://minio.github.io/minio-java/io/minio/BucketExistsArgs.html [EnableObjectLegalHoldArgs]: http://minio.github.io/minio-java/io/minio/EnableObjectLegalHoldArgs.html [DisableObjectLegalHoldArgs]: http://minio.github.io/minio-java/io/minio/DisableObjectLegalHoldArgs.html -[IsObjectLegalHoldEnabledArgs]: http://minio.github.io/minio-java/io/minio/IsObjectLegalHoldEnabledArgs.html \ No newline at end of file +[IsObjectLegalHoldEnabledArgs]: http://minio.github.io/minio-java/io/minio/IsObjectLegalHoldEnabledArgs.html +[ListenBucketNotificationArgs]: http://minio.github.io/minio-java/io/minio/ListenBucketNotificationArgs.html diff --git a/examples/ListenBucketNotification.java b/examples/ListenBucketNotification.java index 430da67fb..88e2ea890 100644 --- a/examples/ListenBucketNotification.java +++ b/examples/ListenBucketNotification.java @@ -15,6 +15,7 @@ */ import io.minio.CloseableIterator; +import io.minio.ListenBucketNotificationArgs; import io.minio.MinioClient; import io.minio.Result; import io.minio.errors.MinioException; @@ -38,7 +39,13 @@ public static void main(String[] args) String[] events = {"s3:ObjectCreated:*", "s3:ObjectAccessed:*"}; try (CloseableIterator> ci = - minioClient.listenBucketNotification("bcketName", "", "", events)) { + minioClient.listenBucketNotification( + ListenBucketNotificationArgs.builder() + .bucket("bucketName") + .prefix("") + .suffix("") + .events(events) + .build())) { while (ci.hasNext()) { NotificationRecords records = ci.next().get(); Event event = records.events().get(0); diff --git a/functional/FunctionalTest.java b/functional/FunctionalTest.java index 54a6fa01c..9203b18b0 100644 --- a/functional/FunctionalTest.java +++ b/functional/FunctionalTest.java @@ -44,6 +44,7 @@ import io.minio.IsObjectLegalHoldEnabledArgs; import io.minio.IsVersioningEnabledArgs; import io.minio.ListObjectsArgs; +import io.minio.ListenBucketNotificationArgs; import io.minio.MakeBucketArgs; import io.minio.MinioClient; import io.minio.ObjectStat; @@ -4143,12 +4144,11 @@ public static void removeAllBucketNotification_test1() throws Exception { } } - /** Test: listenBucketNotification(String bucketName). */ + /** Test: listenBucketNotification(ListenBucketNotificationArgs args). */ public static void listenBucketNotification_test1() throws Exception { + String methodName = "listenBucketNotification(ListenBucketNotificationArgs args)"; if (!mintEnv) { - System.out.println( - "Test: listenBucketNotification(String bucketName, String prefix, " - + "String suffix, String[] events)"); + System.out.println("Test: " + methodName); } long startTime = System.currentTimeMillis(); @@ -4159,7 +4159,14 @@ public static void listenBucketNotification_test1() throws Exception { client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).region(region).build()); String[] events = {"s3:ObjectCreated:*", "s3:ObjectAccessed:*"}; - ci = client.listenBucketNotification(bucketName, "prefix", "suffix", events); + ci = + client.listenBucketNotification( + ListenBucketNotificationArgs.builder() + .bucket(bucketName) + .prefix("prefix") + .suffix("suffix") + .events(events) + .build()); client.putObject(bucketName, "prefix-random-suffix", file, new PutObjectOptions(1 * KB, -1)); @@ -4182,33 +4189,9 @@ public static void listenBucketNotification_test1() throws Exception { } } - mintSuccessLog( - "listenBucketNotification(String bucketName, String prefix, " - + "String suffix, String[] events)", - null, - startTime); + mintSuccessLog(methodName, null, startTime); } catch (Exception e) { - if (e instanceof ErrorResponseException) { - ErrorResponseException exp = (ErrorResponseException) e; - ErrorResponse errorResponse = exp.errorResponse(); - if (errorResponse != null && errorResponse.errorCode() == ErrorCode.NOT_IMPLEMENTED) { - mintIgnoredLog( - "listenBucketNotification(String bucketName, String prefix, " - + "String suffix, String[] events)", - null, - startTime); - return; - } - } - - mintFailedLog( - "listenBucketNotification(String bucketName, String prefix, " - + "String suffix, String[] events)", - null, - startTime, - null, - e.toString() + " >>> " + Arrays.toString(e.getStackTrace())); - throw e; + handleException(methodName, null, startTime, e); } finally { if (ci != null) { ci.close();