From 9df0f9394a774a15295206c49f584470022416db Mon Sep 17 00:00:00 2001 From: athakor Date: Fri, 26 Jun 2020 10:34:56 +0530 Subject: [PATCH 01/18] feat: expose bucket notifications apis --- .../google/cloud/storage/Notification.java | 9 + .../cloud/storage/NotificationInfo.java | 309 ++++++++++++++++++ .../com/google/cloud/storage/Storage.java | 33 ++ .../com/google/cloud/storage/StorageImpl.java | 20 ++ .../cloud/storage/spi/v1/HttpStorageRpc.java | 15 + .../storage/spi/v1/HttpStorageRpcSpans.java | 2 + .../cloud/storage/spi/v1/StorageRpc.java | 8 + .../storage/testing/StorageRpcTestBase.java | 5 + .../cloud/storage/NotificationInfoTest.java | 103 ++++++ .../cloud/storage/StorageImplMockitoTest.java | 85 +++++ .../testing/StorageRpcTestBaseTest.java | 11 + 11 files changed, 600 insertions(+) create mode 100644 google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java create mode 100644 google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java create mode 100644 google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java new file mode 100644 index 000000000..f91241b38 --- /dev/null +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -0,0 +1,9 @@ +package com.google.cloud.storage; + +public class Notification extends NotificationInfo { + + Notification(Builder builder) { + super(builder); + } + +} diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java new file mode 100644 index 000000000..7b8e128af --- /dev/null +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java @@ -0,0 +1,309 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.storage; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.api.pathtemplate.PathTemplate; +import com.google.api.services.storage.model.Notification; +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Google Storage Notification metadata; + * + * @see Concepts and + * Terminology + */ +public class NotificationInfo implements Serializable { + + private static final long serialVersionUID = 5725883368559753810L; + private static final PathTemplate PATH_TEMPLATE = + PathTemplate.createWithoutUrlEncoding("projects/{project}/topics/{topic}"); + + public enum PayloadFormat { + JSON_API_V1, + NONE + } + + static final Function FROM_PB_FUNCTION = + new Function() { + @Override + public NotificationInfo apply(Notification pb) { + return NotificationInfo.fromPb(pb); + } + }; + static final Function TO_PB_FUNCTION = + new Function() { + @Override + public Notification apply(NotificationInfo NotificationInfo) { + return NotificationInfo.toPb(); + } + }; + private final String generatedId; + private final String topic; + private final List eventTypes; + private final Map customAttributes; + private final PayloadFormat payloadFormat; + private final String objectNamePrefix; + private final String etag; + private final String selfLink; + + public static final class Builder { + + private String generatedId; + private String topic; + private List eventTypes; + private Map customAttributes; + private PayloadFormat payloadFormat; + private String objectNamePrefix; + private String etag; + private String selfLink; + + Builder(String topic) { + this.topic = topic; + } + + Builder(NotificationInfo NotificationInfo) { + generatedId = NotificationInfo.generatedId; + etag = NotificationInfo.etag; + selfLink = NotificationInfo.selfLink; + topic = NotificationInfo.topic; + eventTypes = NotificationInfo.eventTypes; + customAttributes = NotificationInfo.customAttributes; + payloadFormat = NotificationInfo.payloadFormat; + objectNamePrefix = NotificationInfo.objectNamePrefix; + } + + Builder setGeneratedId(String generatedId) { + this.generatedId = generatedId; + return this; + } + + Builder setSelfLink(String selfLink) { + this.selfLink = selfLink; + return this; + } + + /** The name of the topic. It must have the format "projects/{project}/topics/{topic}". */ + public Builder setTopic(String topic) { + this.topic = topic; + return this; + } + + public Builder setPayloadFormat(PayloadFormat payloadFormat) { + this.payloadFormat = payloadFormat; + return this; + } + + public Builder setObjectNamePrefix(String objectNamePrefix) { + this.objectNamePrefix = objectNamePrefix; + return this; + } + + public Builder setEventTypes(Iterable eventTypes) { + this.eventTypes = eventTypes != null ? ImmutableList.copyOf(eventTypes) : null; + return this; + } + + Builder setEtag(String etag) { + this.etag = etag; + return this; + } + + public Builder setCustomAttributes(Map customAttributes) { + this.customAttributes = + customAttributes != null ? ImmutableMap.copyOf(customAttributes) : null; + return this; + } + + public NotificationInfo build() { + checkNotNull(topic); + return new NotificationInfo(this); + } + } + + NotificationInfo(Builder builder) { + generatedId = builder.generatedId; + etag = builder.etag; + selfLink = builder.selfLink; + topic = builder.topic; + eventTypes = builder.eventTypes; + customAttributes = builder.customAttributes; + payloadFormat = builder.payloadFormat; + objectNamePrefix = builder.objectNamePrefix; + } + + /** Returns the service-generated id for the notification. */ + public String getGeneratedId() { + return generatedId; + } + + /** Returns the topic to which this subscription publishes. */ + public String getTopic() { + return topic; + } + + /** Returns the canonical URI of this topic as a string. */ + public String getSelfLink() { + return selfLink; + } + + /** Returns the desired content of the Payload. */ + public PayloadFormat getPayloadFormat() { + return payloadFormat; + } + + /** Returns the object name prefix for which this notification configuration applies. */ + public String getObjectNamePrefix() { + return objectNamePrefix; + } + + /** + * Returns HTTP 1.1 Entity tag for the notification. + * + * @see Entity Tags + */ + public String getEtag() { + return etag; + } + + /** + * Returns the list of event types that this notification will apply to. If empty, notifications + * will be sent on all event types. + * + * @see Cross-Origin Resource Sharing + * (CORS) + */ + public List getEventTypes() { + return eventTypes; + } + + /** + * Returns the list of additional attributes to attach to each Cloud PubSub message published for + * this notification subscription. + * + * @see + * About Access Control Lists + */ + public Map getCustomAttributes() { + return customAttributes; + } + + /** Returns a builder for the current notification. */ + public Builder toBuilder() { + return new Builder(this); + } + + @Override + public int hashCode() { + return Objects.hash(getTopic()); + } + + @Override + public boolean equals(Object obj) { + return obj == this + || obj != null + && obj.getClass().equals(NotificationInfo.class) + && Objects.equals(toPb(), ((NotificationInfo) obj).toPb()); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("topic", getTopic()).toString(); + } + + Notification toPb() { + Notification notificationPb = new Notification(); + notificationPb.setId(generatedId); + notificationPb.setEtag(etag); + if (customAttributes != null) { + notificationPb.setCustomAttributes(customAttributes); + } + if (eventTypes != null) { + notificationPb.setEventTypes(eventTypes); + } + if (objectNamePrefix != null) { + notificationPb.setObjectNamePrefix(objectNamePrefix); + } + if (payloadFormat != null) { + notificationPb.setPayloadFormat(payloadFormat.toString()); + } else { + notificationPb.setPayloadFormat(PayloadFormat.NONE.toString()); + } + notificationPb.setSelfLink(selfLink); + notificationPb.setTopic(topic); + + return notificationPb; + } + + /** + * Creates a {@code NotificationInfo} object for the provided topic name. + * + * @param topic The name of the topic. It must have the format + * "projects/{project}/topics/{topic}". + */ + public static NotificationInfo of(String topic) { + PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); + return newBuilder(topic).build(); + } + + /** + * Returns a {@code NotificationInfo} builder where the topic's name is set to the provided name. + * + * @param topic The name of the topic. It must have the format + * "projects/{project}/topics/{topic}". + */ + public static Builder newBuilder(String topic) { + PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); + return new Builder(topic); + } + + static NotificationInfo fromPb(Notification notificationPb) { + Builder builder = newBuilder(notificationPb.getTopic()); + if (notificationPb.getId() != null) { + builder.setGeneratedId(notificationPb.getId()); + } + if (notificationPb.getEtag() != null) { + builder.setEtag(notificationPb.getEtag()); + } + if (notificationPb.getCustomAttributes() != null) { + builder.setCustomAttributes(notificationPb.getCustomAttributes()); + } + if (notificationPb.getSelfLink() != null) { + builder.setSelfLink(notificationPb.getSelfLink()); + } + if (notificationPb.getObjectNamePrefix() != null) { + builder.setObjectNamePrefix(notificationPb.getObjectNamePrefix()); + } + if (notificationPb.getTopic() != null) { + builder.setTopic(notificationPb.getTopic()); + } + if (notificationPb.getEventTypes() != null) { + builder.setEventTypes(notificationPb.getEventTypes()); + } + if (notificationPb.getPayloadFormat() != null) { + builder.setPayloadFormat(PayloadFormat.valueOf(notificationPb.getPayloadFormat())); + } + return builder.build(); + } +} diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 211859945..0dbdfab7c 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3625,4 +3625,37 @@ List testIamPermissions( * @throws StorageException upon failure */ ServiceAccount getServiceAccount(String projectId); + + + /** + * Creates a notification with the specified entity on the specified bucket. + * + * @return the notification that was created. + * @throws StorageException upon failure + */ + Notification createNotification(String bucket, NotificationInfo notification); + + /** + * Get the notification with the specified name on the specified object. + * + * @return the notification object that exist on the bucket. + * @throws StorageException upon failure + */ + Notification getNotification(String bucket, String notification); + + /** + * List the notifications for the provided bucket. + * + * @return a list of {@link Notification} objects that exist on the bucket. + * @throws StorageException upon failure + */ + List listNotifications(String bucket); + + /** + * Deletes the notification with the specified name on the specified object. + * + * @return {@code true} if the notification was deleted, {@code false} if it was not found + * @throws StorageException upon failure + */ + boolean deleteNotification(String bucket, String notification); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index e8263767d..eb457119f 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -1374,6 +1374,26 @@ private U run(ResultRetryAlgorithm algorithm, Callable c, Function< return Retrying.run(getOptions(), algorithm, c, f); } + @Override + public Notification createNotification(final String bucket, NotificationInfo notification) { + return null; + } + + @Override + public Notification getNotification(final String bucket, final String notification) { + return null; + } + + @Override + public List listNotifications(final String bucket) { + return null; + } + + @Override + public boolean deleteNotification(final String bucket, final String notification) { + return false; + } + private static void addToOptionMap( StorageRpc.Option option, T defaultValue, Map map) { addToOptionMap(option, option, defaultValue, map); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java index 71b952c43..6a905199d 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java @@ -1602,6 +1602,21 @@ public Notification createNotification(String bucket, Notification notification) } } + @Override + public Notification getNotification(String bucket, String notification) { + Span span = startSpan(HttpStorageRpcSpans.SPAN_NAME_GET_NOTIFICATION); + Scope scope = tracer.withSpan(span); + try { + return storage.notifications().get(bucket, notification).execute(); + } catch (IOException ex) { + span.setStatus(Status.UNKNOWN.withDescription(ex.getMessage())); + throw translate(ex); + } finally { + scope.close(); + span.end(); + } + } + @Override public Bucket lockRetentionPolicy(Bucket bucket, Map options) { Span span = startSpan(HttpStorageRpcSpans.SPAN_LOCK_RETENTION_POLICY); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java index 4e169d478..498a8f474 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java @@ -89,6 +89,8 @@ class HttpStorageRpcSpans { static final String SPAN_NAME_LIST_NOTIFICATIONS = getTraceSpanName("listNotifications(String)"); static final String SPAN_NAME_CREATE_NOTIFICATION = getTraceSpanName("createNotification(String,Notification)"); + static final String SPAN_NAME_GET_NOTIFICATION = + getTraceSpanName("getNotification(String,String)"); static final String SPAN_LOCK_RETENTION_POLICY = getTraceSpanName("lockRetentionPolicy(String,Long)"); static final String SPAN_NAME_GET_SERVICE_ACCOUNT = getTraceSpanName("getServiceAccount(String)"); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java index 201078efa..f9fbb1b51 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java @@ -584,6 +584,14 @@ TestIamPermissionsResponse testIamPermissions( */ Notification createNotification(String bucket, Notification notification); + /** + * Get the notification with the specified name on the specified object. + * + * @return the notification object that exist on the bucket. + * @throws StorageException upon failure + */ + Notification getNotification(String bucket, String notification); + /** * Lock retention policy for the provided bucket. * diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java index 43e29d011..f420ed1e6 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java @@ -301,6 +301,11 @@ public Notification createNotification(String bucket, Notification notification) throw new UnsupportedOperationException("Not implemented yet"); } + @Override + public Notification getNotification(String bucket, String notification) { + throw new UnsupportedOperationException("Not implemented yet"); + } + @Override public Bucket lockRetentionPolicy(Bucket bucket, Map options) { throw new UnsupportedOperationException("Not implemented yet"); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java new file mode 100644 index 000000000..fa3d2f2cd --- /dev/null +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java @@ -0,0 +1,103 @@ + +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.storage; + +import static org.junit.Assert.assertEquals; + +import com.google.cloud.storage.NotificationInfo.PayloadFormat; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.List; +import java.util.Map; +import org.junit.Test; + +public class NotificationInfoTest { + + private static final String ETAG = "0xFF00"; + private static final String GENERATED_ID = "B/N:1"; + private static final String SELF_LINK = "http://storage/b/n"; + private static final List EVENT_TYPES = + ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); + private static final String OBJECT_NAME_PREFIX = "index.html"; + private static final PayloadFormat PAYLOAD_FORMAT = PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final String TOPIC = "projects/myProject/topics/topic1"; + private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); + private static final NotificationInfo NOTIFICATION_INFO = + NotificationInfo.newBuilder(TOPIC) + .setEtag(ETAG) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setSelfLink(SELF_LINK) + .setEventTypes(EVENT_TYPES) + .setObjectNamePrefix(OBJECT_NAME_PREFIX) + .setPayloadFormat(PAYLOAD_FORMAT) + .setGeneratedId(GENERATED_ID) + .build(); + + @Test + public void testToBuilder() { + compareBuckets(NOTIFICATION_INFO, NOTIFICATION_INFO.toBuilder().build()); + NotificationInfo bucketInfo = NOTIFICATION_INFO.toBuilder().setGeneratedId("id").build(); + assertEquals("id", bucketInfo.getGeneratedId()); + bucketInfo = bucketInfo.toBuilder().setGeneratedId(GENERATED_ID).build(); + compareBuckets(NOTIFICATION_INFO, bucketInfo); + } + + @Test + public void testToBuilderIncomplete() { + NotificationInfo incompleteBucketInfo = NotificationInfo.newBuilder(TOPIC).build(); + compareBuckets(incompleteBucketInfo, incompleteBucketInfo.toBuilder().build()); + } + + @Test + public void testOf() { + NotificationInfo bucketInfo = NotificationInfo.of(TOPIC); + assertEquals(TOPIC, bucketInfo.getTopic()); + } + + @Test + public void testBuilder() { + assertEquals(ETAG, NOTIFICATION_INFO.getEtag()); + assertEquals(GENERATED_ID, NOTIFICATION_INFO.getGeneratedId()); + assertEquals(SELF_LINK, NOTIFICATION_INFO.getSelfLink()); + assertEquals(EVENT_TYPES, NOTIFICATION_INFO.getEventTypes()); + assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION_INFO.getObjectNamePrefix()); + assertEquals(PAYLOAD_FORMAT, NOTIFICATION_INFO.getPayloadFormat()); + assertEquals(TOPIC, NOTIFICATION_INFO.getTopic()); + assertEquals(CUSTOM_ATTRIBUTES, NOTIFICATION_INFO.getCustomAttributes()); + } + + @Test + public void testToPbAndFromPb() { + compareBuckets(NOTIFICATION_INFO, NotificationInfo.fromPb(NOTIFICATION_INFO.toPb())); + NotificationInfo bucketInfo = + NotificationInfo.of(TOPIC).toBuilder().setPayloadFormat(PayloadFormat.NONE).build(); + compareBuckets(bucketInfo, NotificationInfo.fromPb(bucketInfo.toPb())); + } + + private void compareBuckets(NotificationInfo expected, NotificationInfo value) { + assertEquals(expected, value); + assertEquals(expected.getGeneratedId(), value.getGeneratedId()); + assertEquals(expected.getCustomAttributes(), value.getCustomAttributes()); + assertEquals(expected.getEtag(), value.getEtag()); + assertEquals(expected.getSelfLink(), value.getSelfLink()); + assertEquals(expected.getEventTypes(), value.getEventTypes()); + assertEquals(expected.getObjectNamePrefix(), value.getObjectNamePrefix()); + assertEquals(expected.getPayloadFormat(), value.getPayloadFormat()); + assertEquals(expected.getTopic(), value.getTopic()); + } +} \ No newline at end of file diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java index 52c312b47..7fbbc8843 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java @@ -60,6 +60,7 @@ import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; +import java.util.List; import java.util.Map; import javax.crypto.spec.SecretKeySpec; import org.junit.Before; @@ -366,6 +367,38 @@ public long millisTime() { .put('~', "~") .build(); + // Notification + private static final String ETAG = "0xFF00"; + private static final String GENERATED_ID = "B/N:1"; + private static final String SELF_LINK = "http://storage/b/n"; + private static final List EVENT_TYPES = + ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); + private static final String OBJECT_NAME_PREFIX = "index.html"; + private static final NotificationInfo.PayloadFormat PAYLOAD_FORMAT = + NotificationInfo.PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final String TOPIC = "projects/myProject/topics/topic1"; + private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); + private static final NotificationInfo NOTIFICATION_INFO_01 = + NotificationInfo.newBuilder(TOPIC) + .setEtag(ETAG) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setSelfLink(SELF_LINK) + .setEventTypes(EVENT_TYPES) + .setObjectNamePrefix(OBJECT_NAME_PREFIX) + .setPayloadFormat(PAYLOAD_FORMAT) + .setGeneratedId(GENERATED_ID) + .build(); + private static final NotificationInfo NOTIFICATION_INFO_02 = + NotificationInfo.newBuilder(TOPIC) + .setEtag(ETAG) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setSelfLink(SELF_LINK) + .setEventTypes(EVENT_TYPES) + .setObjectNamePrefix(OBJECT_NAME_PREFIX) + .setPayloadFormat(PAYLOAD_FORMAT) + .setGeneratedId(GENERATED_ID) + .build(); + private static final String ACCOUNT = "account"; private static PrivateKey privateKey; private static PublicKey publicKey; @@ -1643,4 +1676,56 @@ public void testWriterFailure() { assertSame(STORAGE_FAILURE, e.getCause()); } } + @Test + public void testCreateNotification() { + Notification notification = NOTIFICATION_INFO_01.toPb(); + EasyMock.expect(storageRpcMock.createNotification(BUCKET_NAME1, notification)) + .andReturn(notification); + EasyMock.replay(storageRpcMock); + initializeService(); + Notification remoteNotification = + storage.createNotification(BUCKET_NAME1, NOTIFICATION_INFO_01); + compareBucketsNotification(remoteNotification); + } + + @Test + public void testGetNotification() { + doReturn(NOTIFICATION_INFO_01.toPb()) + .when(storageRpcMock) + .getNotification(BUCKET_NAME1,GENERATED_ID); + initializeService(); + Notification notification = storage.getNotification(BUCKET_NAME1, GENERATED_ID); + compareBucketsNotification(notification); + } + + @Test + public void testListNotification() { + doReturn(Arrays.asList(NOTIFICATION_INFO_01.toPb(), NOTIFICATION_INFO_02.toPb())) + .when(storageRpcMock) + .listNotifications(BUCKET_NAME1); + initializeService(); + List notifications = storage.listNotifications(BUCKET_NAME1); + assertEquals(2, notifications.size()); + } + + @Test + public void testDeleteNotification() { + doReturn(true) + .when(storageRpcMock) + .deleteNotification(BUCKET_NAME1, GENERATED_ID); + initializeService(); + Boolean isDeleted = storage.deleteNotification(BUCKET_NAME1, GENERATED_ID); + assertEquals(isDeleted, Boolean.TRUE); + } + + private void compareBucketsNotification(Notification value) { + assertEquals(GENERATED_ID, value.getId()); + assertEquals(CUSTOM_ATTRIBUTES, value.getCustomAttributes()); + assertEquals(ETAG, value.getEtag()); + assertEquals(SELF_LINK, value.getSelfLink()); + assertEquals(EVENT_TYPES, value.getEventTypes()); + assertEquals(OBJECT_NAME_PREFIX, value.getObjectNamePrefix()); + assertEquals(PAYLOAD_FORMAT.name(), value.getPayloadFormat()); + assertEquals(TOPIC, value.getTopic()); + } } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/StorageRpcTestBaseTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/StorageRpcTestBaseTest.java index b798ad572..affd6fb5c 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/StorageRpcTestBaseTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/StorageRpcTestBaseTest.java @@ -577,6 +577,17 @@ public Notification call() { }; } + @Test + public void testGetNotification() { + rpc = + new Callable() { + @Override + public Notification call() { + return STORAGE_RPC.getNotification("bucket", "notification"); + } + }; + } + @Test public void testLockRetentionPolicy() { rpc = From ce09c25467aa127bb49f9fea26a1f7f11e9f6169 Mon Sep 17 00:00:00 2001 From: athakor Date: Mon, 29 Jun 2020 21:35:01 +0530 Subject: [PATCH 02/18] feat: expose bucket notifications apis --- .../clirr-ignored-differences.xml | 25 + google-cloud-storage/pom.xml | 5 + .../google/cloud/storage/Notification.java | 134 ++++- .../cloud/storage/NotificationInfo.java | 489 ++++++++++-------- .../com/google/cloud/storage/Storage.java | 3 +- .../com/google/cloud/storage/StorageImpl.java | 81 ++- .../storage/spi/v1/HttpStorageRpcSpans.java | 2 +- .../cloud/storage/NotificationInfoTest.java | 135 +++-- .../cloud/storage/NotificationTest.java | 129 +++++ .../cloud/storage/StorageImplMockitoTest.java | 69 ++- .../cloud/storage/it/ITStorageTest.java | 109 +++- .../testing/StorageRpcTestBaseTest.java | 20 +- pom.xml | 6 + 13 files changed, 838 insertions(+), 369 deletions(-) create mode 100644 google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml index c45b439cc..9f137f62c 100644 --- a/google-cloud-storage/clirr-ignored-differences.xml +++ b/google-cloud-storage/clirr-ignored-differences.xml @@ -11,4 +11,29 @@ BucketInfo$LifecycleRule$LifecycleAction() 7004 + + com/google/cloud/storage/Storage + com.google.cloud.storage.Notification createNotification(java.lang.String, com.google.cloud.storage.NotificationInfo) + 7012 + + + com/google/cloud/storage/Storage + com.google.cloud.storage.Notification getNotification(java.lang.String, java.lang.String) + 7012 + + + com/google/cloud/storage/Storage + java.util.List listNotifications(java.lang.String) + 7012 + + + com/google/cloud/storage/Storage + boolean deleteNotification(java.lang.String, java.lang.String) + 7012 + + + com/google/cloud/storage/spi/v1/StorageRpc + com.google.api.services.storage.model.Notification getNotification(java.lang.String, java.lang.String) + 7012 + diff --git a/google-cloud-storage/pom.xml b/google-cloud-storage/pom.xml index bddc08608..976f60f6c 100644 --- a/google-cloud-storage/pom.xml +++ b/google-cloud-storage/pom.xml @@ -147,6 +147,11 @@ truth test + + com.google.cloud + google-cloud-pubsub + test + org.easymock easymock diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java index f91241b38..33532f558 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -1,9 +1,139 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.google.cloud.storage; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Objects; + +/** + * Google Storage Notification object; + * + * @see notifications + */ public class Notification extends NotificationInfo { - Notification(Builder builder) { - super(builder); + private final StorageOptions options; + private transient Storage storage; + + /** Builder for {@code Notification}. */ + public static class Builder extends NotificationInfo.Builder { + private final Storage storage; + private final NotificationInfo.BuilderImpl infoBuilder; + + Builder(Notification notification) { + this.storage = notification.storage; + this.infoBuilder = new NotificationInfo.BuilderImpl(notification); + } + + @Override + public Builder setGeneratedId(String generatedId) { + infoBuilder.setGeneratedId(generatedId); + return this; + } + + @Override + public Builder setSelfLink(String selfLink) { + infoBuilder.setSelfLink(selfLink); + return this; + } + + @Override + public Builder setTopic(String topic) { + infoBuilder.setTopic(topic); + return this; + } + + @Override + public Builder setPayloadFormat(PayloadFormat payloadFormat) { + infoBuilder.setPayloadFormat(payloadFormat); + return this; + } + + @Override + public Builder setObjectNamePrefix(String objectNamePrefix) { + infoBuilder.setObjectNamePrefix(objectNamePrefix); + return this; } + @Override + public Builder setEventTypes(Iterable eventTypes) { + infoBuilder.setEventTypes(eventTypes); + return this; + } + + @Override + public Builder setEtag(String etag) { + infoBuilder.setEtag(etag); + return this; + } + + @Override + public Builder setCustomAttributes(Map customAttributes) { + infoBuilder.setCustomAttributes(customAttributes); + return this; + } + + @Override + public Notification build() { + return new Notification(storage, infoBuilder); + } + } + + Notification(Storage storage, NotificationInfo.BuilderImpl infoBuilder) { + super(infoBuilder); + this.storage = checkNotNull(storage); + this.options = storage.getOptions(); + } + + /** Returns the notification's {@code Storage} object used to issue requests. */ + public Storage getStorage() { + return storage; + } + + @Override + public Builder toBuilder() { + return new Notification.Builder(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + Notification that = (Notification) o; + return Objects.equals(toPb(), that.toPb()) && Objects.equals(options, that.options); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), options, storage); + } + + static Notification fromPb( + Storage storage, com.google.api.services.storage.model.Notification notificationPb) { + return new Notification( + storage, new NotificationInfo.BuilderImpl(NotificationInfo.fromPb(notificationPb))); + } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java index 7b8e128af..d9653fec7 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java @@ -36,274 +36,307 @@ */ public class NotificationInfo implements Serializable { - private static final long serialVersionUID = 5725883368559753810L; - private static final PathTemplate PATH_TEMPLATE = - PathTemplate.createWithoutUrlEncoding("projects/{project}/topics/{topic}"); - - public enum PayloadFormat { - JSON_API_V1, - NONE - } - - static final Function FROM_PB_FUNCTION = - new Function() { - @Override - public NotificationInfo apply(Notification pb) { - return NotificationInfo.fromPb(pb); - } - }; - static final Function TO_PB_FUNCTION = - new Function() { - @Override - public Notification apply(NotificationInfo NotificationInfo) { - return NotificationInfo.toPb(); - } - }; - private final String generatedId; - private final String topic; - private final List eventTypes; - private final Map customAttributes; - private final PayloadFormat payloadFormat; - private final String objectNamePrefix; - private final String etag; - private final String selfLink; - - public static final class Builder { - - private String generatedId; - private String topic; - private List eventTypes; - private Map customAttributes; - private PayloadFormat payloadFormat; - private String objectNamePrefix; - private String etag; - private String selfLink; - - Builder(String topic) { - this.topic = topic; + private static final long serialVersionUID = 5725883368559753810L; + private static final PathTemplate PATH_TEMPLATE = + PathTemplate.createWithoutUrlEncoding("projects/{project}/topics/{topic}"); + + public enum PayloadFormat { + JSON_API_V1, + NONE + } + + static final Function FROM_PB_FUNCTION = + new Function() { + @Override + public NotificationInfo apply(Notification pb) { + return NotificationInfo.fromPb(pb); } - - Builder(NotificationInfo NotificationInfo) { - generatedId = NotificationInfo.generatedId; - etag = NotificationInfo.etag; - selfLink = NotificationInfo.selfLink; - topic = NotificationInfo.topic; - eventTypes = NotificationInfo.eventTypes; - customAttributes = NotificationInfo.customAttributes; - payloadFormat = NotificationInfo.payloadFormat; - objectNamePrefix = NotificationInfo.objectNamePrefix; + }; + static final Function TO_PB_FUNCTION = + new Function() { + @Override + public Notification apply(NotificationInfo NotificationInfo) { + return NotificationInfo.toPb(); } + }; + private final String generatedId; + private final String topic; + private final List eventTypes; + private final Map customAttributes; + private final PayloadFormat payloadFormat; + private final String objectNamePrefix; + private final String etag; + private final String selfLink; - Builder setGeneratedId(String generatedId) { - this.generatedId = generatedId; - return this; - } + /** Builder for {@code NotificatioInfo}. */ + public abstract static class Builder { + Builder() {} - Builder setSelfLink(String selfLink) { - this.selfLink = selfLink; - return this; - } + public abstract Builder setGeneratedId(String generatedId); - /** The name of the topic. It must have the format "projects/{project}/topics/{topic}". */ - public Builder setTopic(String topic) { - this.topic = topic; - return this; - } + public abstract Builder setSelfLink(String selfLink); - public Builder setPayloadFormat(PayloadFormat payloadFormat) { - this.payloadFormat = payloadFormat; - return this; - } + public abstract Builder setTopic(String topic); - public Builder setObjectNamePrefix(String objectNamePrefix) { - this.objectNamePrefix = objectNamePrefix; - return this; - } + public abstract Builder setPayloadFormat(PayloadFormat payloadFormat); - public Builder setEventTypes(Iterable eventTypes) { - this.eventTypes = eventTypes != null ? ImmutableList.copyOf(eventTypes) : null; - return this; - } + public abstract Builder setObjectNamePrefix(String objectNamePrefix); - Builder setEtag(String etag) { - this.etag = etag; - return this; - } + public abstract Builder setEventTypes(Iterable eventTypes); - public Builder setCustomAttributes(Map customAttributes) { - this.customAttributes = - customAttributes != null ? ImmutableMap.copyOf(customAttributes) : null; - return this; - } + public abstract Builder setEtag(String etag); - public NotificationInfo build() { - checkNotNull(topic); - return new NotificationInfo(this); - } - } + public abstract Builder setCustomAttributes(Map customAttributes); - NotificationInfo(Builder builder) { - generatedId = builder.generatedId; - etag = builder.etag; - selfLink = builder.selfLink; - topic = builder.topic; - eventTypes = builder.eventTypes; - customAttributes = builder.customAttributes; - payloadFormat = builder.payloadFormat; - objectNamePrefix = builder.objectNamePrefix; - } + /** Creates a {@code NotificationInfo} object. */ + public abstract NotificationInfo build(); + } - /** Returns the service-generated id for the notification. */ - public String getGeneratedId() { - return generatedId; - } + public static final class BuilderImpl extends Builder { - /** Returns the topic to which this subscription publishes. */ - public String getTopic() { - return topic; - } + private String generatedId; + private String topic; + private List eventTypes; + private Map customAttributes; + private PayloadFormat payloadFormat; + private String objectNamePrefix; + private String etag; + private String selfLink; - /** Returns the canonical URI of this topic as a string. */ - public String getSelfLink() { - return selfLink; + BuilderImpl(String topic) { + this.topic = topic; } - /** Returns the desired content of the Payload. */ - public PayloadFormat getPayloadFormat() { - return payloadFormat; + BuilderImpl(NotificationInfo NotificationInfo) { + generatedId = NotificationInfo.generatedId; + etag = NotificationInfo.etag; + selfLink = NotificationInfo.selfLink; + topic = NotificationInfo.topic; + eventTypes = NotificationInfo.eventTypes; + customAttributes = NotificationInfo.customAttributes; + payloadFormat = NotificationInfo.payloadFormat; + objectNamePrefix = NotificationInfo.objectNamePrefix; } - /** Returns the object name prefix for which this notification configuration applies. */ - public String getObjectNamePrefix() { - return objectNamePrefix; + @Override + public Builder setGeneratedId(String generatedId) { + this.generatedId = generatedId; + return this; } - /** - * Returns HTTP 1.1 Entity tag for the notification. - * - * @see Entity Tags - */ - public String getEtag() { - return etag; + @Override + public Builder setSelfLink(String selfLink) { + this.selfLink = selfLink; + return this; } - /** - * Returns the list of event types that this notification will apply to. If empty, notifications - * will be sent on all event types. - * - * @see Cross-Origin Resource Sharing - * (CORS) - */ - public List getEventTypes() { - return eventTypes; + /** The name of the topic. It must have the format "projects/{project}/topics/{topic}". */ + @Override + public Builder setTopic(String topic) { + this.topic = topic; + return this; } - /** - * Returns the list of additional attributes to attach to each Cloud PubSub message published for - * this notification subscription. - * - * @see - * About Access Control Lists - */ - public Map getCustomAttributes() { - return customAttributes; + @Override + public Builder setPayloadFormat(PayloadFormat payloadFormat) { + this.payloadFormat = payloadFormat; + return this; } - /** Returns a builder for the current notification. */ - public Builder toBuilder() { - return new Builder(this); + @Override + public Builder setObjectNamePrefix(String objectNamePrefix) { + this.objectNamePrefix = objectNamePrefix; + return this; } @Override - public int hashCode() { - return Objects.hash(getTopic()); + public Builder setEventTypes(Iterable eventTypes) { + this.eventTypes = eventTypes != null ? ImmutableList.copyOf(eventTypes) : null; + return this; } @Override - public boolean equals(Object obj) { - return obj == this - || obj != null - && obj.getClass().equals(NotificationInfo.class) - && Objects.equals(toPb(), ((NotificationInfo) obj).toPb()); + public Builder setEtag(String etag) { + this.etag = etag; + return this; } @Override - public String toString() { - return MoreObjects.toStringHelper(this).add("topic", getTopic()).toString(); + public Builder setCustomAttributes(Map customAttributes) { + this.customAttributes = + customAttributes != null ? ImmutableMap.copyOf(customAttributes) : null; + return this; } - Notification toPb() { - Notification notificationPb = new Notification(); - notificationPb.setId(generatedId); - notificationPb.setEtag(etag); - if (customAttributes != null) { - notificationPb.setCustomAttributes(customAttributes); - } - if (eventTypes != null) { - notificationPb.setEventTypes(eventTypes); - } - if (objectNamePrefix != null) { - notificationPb.setObjectNamePrefix(objectNamePrefix); - } - if (payloadFormat != null) { - notificationPb.setPayloadFormat(payloadFormat.toString()); - } else { - notificationPb.setPayloadFormat(PayloadFormat.NONE.toString()); - } - notificationPb.setSelfLink(selfLink); - notificationPb.setTopic(topic); - - return notificationPb; + @Override + public NotificationInfo build() { + checkNotNull(topic); + return new NotificationInfo(this); } - - /** - * Creates a {@code NotificationInfo} object for the provided topic name. - * - * @param topic The name of the topic. It must have the format - * "projects/{project}/topics/{topic}". - */ - public static NotificationInfo of(String topic) { - PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); - return newBuilder(topic).build(); + } + + NotificationInfo(BuilderImpl builder) { + generatedId = builder.generatedId; + etag = builder.etag; + selfLink = builder.selfLink; + topic = builder.topic; + eventTypes = builder.eventTypes; + customAttributes = builder.customAttributes; + payloadFormat = builder.payloadFormat; + objectNamePrefix = builder.objectNamePrefix; + } + + /** Returns the service-generated id for the notification. */ + public String getGeneratedId() { + return generatedId; + } + + /** Returns the topic to which this subscription publishes. */ + public String getTopic() { + return topic; + } + + /** Returns the canonical URI of this topic as a string. */ + public String getSelfLink() { + return selfLink; + } + + /** Returns the desired content of the Payload. */ + public PayloadFormat getPayloadFormat() { + return payloadFormat; + } + + /** Returns the object name prefix for which this notification configuration applies. */ + public String getObjectNamePrefix() { + return objectNamePrefix; + } + + /** + * Returns HTTP 1.1 Entity tag for the notification. + * + * @see Entity Tags + */ + public String getEtag() { + return etag; + } + + /** + * Returns the list of event types that this notification will apply to. If empty, notifications + * will be sent on all event types. + * + * @see Cross-Origin Resource Sharing + * (CORS) + */ + public List getEventTypes() { + return eventTypes; + } + + /** + * Returns the list of additional attributes to attach to each Cloud PubSub message published for + * this notification subscription. + * + * @see + * About Access Control Lists + */ + public Map getCustomAttributes() { + return customAttributes; + } + + /** Returns a builder for the current notification. */ + public Builder toBuilder() { + return new BuilderImpl(this); + } + + @Override + public int hashCode() { + return Objects.hash(getTopic()); + } + + @Override + public boolean equals(Object obj) { + return obj == this + || obj != null + && obj.getClass().equals(NotificationInfo.class) + && Objects.equals(toPb(), ((NotificationInfo) obj).toPb()); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("topic", getTopic()).toString(); + } + + Notification toPb() { + Notification notificationPb = new Notification(); + notificationPb.setId(generatedId); + notificationPb.setEtag(etag); + if (customAttributes != null) { + notificationPb.setCustomAttributes(customAttributes); } - - /** - * Returns a {@code NotificationInfo} builder where the topic's name is set to the provided name. - * - * @param topic The name of the topic. It must have the format - * "projects/{project}/topics/{topic}". - */ - public static Builder newBuilder(String topic) { - PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); - return new Builder(topic); + if (eventTypes != null) { + notificationPb.setEventTypes(eventTypes); } - - static NotificationInfo fromPb(Notification notificationPb) { - Builder builder = newBuilder(notificationPb.getTopic()); - if (notificationPb.getId() != null) { - builder.setGeneratedId(notificationPb.getId()); - } - if (notificationPb.getEtag() != null) { - builder.setEtag(notificationPb.getEtag()); - } - if (notificationPb.getCustomAttributes() != null) { - builder.setCustomAttributes(notificationPb.getCustomAttributes()); - } - if (notificationPb.getSelfLink() != null) { - builder.setSelfLink(notificationPb.getSelfLink()); - } - if (notificationPb.getObjectNamePrefix() != null) { - builder.setObjectNamePrefix(notificationPb.getObjectNamePrefix()); - } - if (notificationPb.getTopic() != null) { - builder.setTopic(notificationPb.getTopic()); - } - if (notificationPb.getEventTypes() != null) { - builder.setEventTypes(notificationPb.getEventTypes()); - } - if (notificationPb.getPayloadFormat() != null) { - builder.setPayloadFormat(PayloadFormat.valueOf(notificationPb.getPayloadFormat())); - } - return builder.build(); + if (objectNamePrefix != null) { + notificationPb.setObjectNamePrefix(objectNamePrefix); + } + if (payloadFormat != null) { + notificationPb.setPayloadFormat(payloadFormat.toString()); + } else { + notificationPb.setPayloadFormat(PayloadFormat.NONE.toString()); + } + notificationPb.setSelfLink(selfLink); + notificationPb.setTopic(topic); + + return notificationPb; + } + + /** + * Creates a {@code NotificationInfo} object for the provided topic name. + * + * @param topic The name of the topic. It must have the format + * "projects/{project}/topics/{topic}". + */ + public static NotificationInfo of(String topic) { + PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); + return newBuilder(topic).build(); + } + + /** + * Returns a {@code NotificationInfo} builder where the topic's name is set to the provided name. + * + * @param topic The name of the topic. It must have the format + * "projects/{project}/topics/{topic}". + */ + public static Builder newBuilder(String topic) { + PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); + return new BuilderImpl(topic); + } + + static NotificationInfo fromPb(Notification notificationPb) { + Builder builder = newBuilder(notificationPb.getTopic()); + if (notificationPb.getId() != null) { + builder.setGeneratedId(notificationPb.getId()); + } + if (notificationPb.getEtag() != null) { + builder.setEtag(notificationPb.getEtag()); + } + if (notificationPb.getCustomAttributes() != null) { + builder.setCustomAttributes(notificationPb.getCustomAttributes()); + } + if (notificationPb.getSelfLink() != null) { + builder.setSelfLink(notificationPb.getSelfLink()); + } + if (notificationPb.getObjectNamePrefix() != null) { + builder.setObjectNamePrefix(notificationPb.getObjectNamePrefix()); + } + if (notificationPb.getTopic() != null) { + builder.setTopic(notificationPb.getTopic()); + } + if (notificationPb.getEventTypes() != null) { + builder.setEventTypes(notificationPb.getEventTypes()); + } + if (notificationPb.getPayloadFormat() != null) { + builder.setPayloadFormat(PayloadFormat.valueOf(notificationPb.getPayloadFormat())); } + return builder.build(); + } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 0dbdfab7c..d0cc60518 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3626,14 +3626,13 @@ List testIamPermissions( */ ServiceAccount getServiceAccount(String projectId); - /** * Creates a notification with the specified entity on the specified bucket. * * @return the notification that was created. * @throws StorageException upon failure */ - Notification createNotification(String bucket, NotificationInfo notification); + Notification createNotification(String bucket, NotificationInfo notificationInfo); /** * Get the notification with the specified name on the specified object. diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index eb457119f..a4345e572 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -1375,23 +1375,94 @@ private U run(ResultRetryAlgorithm algorithm, Callable c, Function< } @Override - public Notification createNotification(final String bucket, NotificationInfo notification) { - return null; + public Notification createNotification( + final String bucket, final NotificationInfo notificationInfo) { + final com.google.api.services.storage.model.Notification notificationPb = + notificationInfo.toPb(); + try { + return Notification.fromPb( + this, + runWithRetries( + new Callable() { + @Override + public com.google.api.services.storage.model.Notification call() { + return storageRpc.createNotification(bucket, notificationPb); + } + }, + getOptions().getRetrySettings(), + EXCEPTION_HANDLER, + getOptions().getClock())); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } } @Override public Notification getNotification(final String bucket, final String notification) { - return null; + try { + com.google.api.services.storage.model.Notification answer = + runWithRetries( + new Callable() { + @Override + public com.google.api.services.storage.model.Notification call() { + return storageRpc.getNotification(bucket, notification); + } + }, + getOptions().getRetrySettings(), + EXCEPTION_HANDLER, + getOptions().getClock()); + return answer == null ? null : Notification.fromPb(this, answer); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } } @Override public List listNotifications(final String bucket) { - return null; + try { + List answer = + runWithRetries( + new Callable>() { + @Override + public List call() { + return storageRpc.listNotifications(bucket); + } + }, + getOptions().getRetrySettings(), + EXCEPTION_HANDLER, + getOptions().getClock()); + return answer == null + ? null + : Lists.transform( + answer, + new Function() { + @Override + public Notification apply( + com.google.api.services.storage.model.Notification notificationPb) { + return Notification.fromPb(getOptions().getService(), notificationPb); + } + }); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } } @Override public boolean deleteNotification(final String bucket, final String notification) { - return false; + try { + return runWithRetries( + new Callable() { + @Override + public Boolean call() { + return storageRpc.deleteNotification(bucket, notification); + } + }, + getOptions().getRetrySettings(), + EXCEPTION_HANDLER, + getOptions().getClock()); + } catch (RetryHelperException e) { + throw StorageException.translateAndThrow(e); + } } private static void addToOptionMap( diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java index 498a8f474..3f3d27d94 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpcSpans.java @@ -90,7 +90,7 @@ class HttpStorageRpcSpans { static final String SPAN_NAME_CREATE_NOTIFICATION = getTraceSpanName("createNotification(String,Notification)"); static final String SPAN_NAME_GET_NOTIFICATION = - getTraceSpanName("getNotification(String,String)"); + getTraceSpanName("getNotification(String,String)"); static final String SPAN_LOCK_RETENTION_POLICY = getTraceSpanName("lockRetentionPolicy(String,Long)"); static final String SPAN_NAME_GET_SERVICE_ACCOUNT = getTraceSpanName("getServiceAccount(String)"); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java index fa3d2f2cd..40b8a5ccf 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java @@ -1,4 +1,3 @@ - /* * Copyright 2020 Google LLC * @@ -28,76 +27,76 @@ public class NotificationInfoTest { - private static final String ETAG = "0xFF00"; - private static final String GENERATED_ID = "B/N:1"; - private static final String SELF_LINK = "http://storage/b/n"; - private static final List EVENT_TYPES = - ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); - private static final String OBJECT_NAME_PREFIX = "index.html"; - private static final PayloadFormat PAYLOAD_FORMAT = PayloadFormat.JSON_API_V1.JSON_API_V1; - private static final String TOPIC = "projects/myProject/topics/topic1"; - private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); - private static final NotificationInfo NOTIFICATION_INFO = - NotificationInfo.newBuilder(TOPIC) - .setEtag(ETAG) - .setCustomAttributes(CUSTOM_ATTRIBUTES) - .setSelfLink(SELF_LINK) - .setEventTypes(EVENT_TYPES) - .setObjectNamePrefix(OBJECT_NAME_PREFIX) - .setPayloadFormat(PAYLOAD_FORMAT) - .setGeneratedId(GENERATED_ID) - .build(); + private static final String ETAG = "0xFF00"; + private static final String GENERATED_ID = "B/N:1"; + private static final String SELF_LINK = "http://storage/b/n"; + private static final List EVENT_TYPES = + ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); + private static final String OBJECT_NAME_PREFIX = "index.html"; + private static final PayloadFormat PAYLOAD_FORMAT = PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final String TOPIC = "projects/myProject/topics/topic1"; + private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); + private static final NotificationInfo NOTIFICATION_INFO = + NotificationInfo.newBuilder(TOPIC) + .setEtag(ETAG) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setSelfLink(SELF_LINK) + .setEventTypes(EVENT_TYPES) + .setObjectNamePrefix(OBJECT_NAME_PREFIX) + .setPayloadFormat(PAYLOAD_FORMAT) + .setGeneratedId(GENERATED_ID) + .build(); - @Test - public void testToBuilder() { - compareBuckets(NOTIFICATION_INFO, NOTIFICATION_INFO.toBuilder().build()); - NotificationInfo bucketInfo = NOTIFICATION_INFO.toBuilder().setGeneratedId("id").build(); - assertEquals("id", bucketInfo.getGeneratedId()); - bucketInfo = bucketInfo.toBuilder().setGeneratedId(GENERATED_ID).build(); - compareBuckets(NOTIFICATION_INFO, bucketInfo); - } + @Test + public void testToBuilder() { + compareBuckets(NOTIFICATION_INFO, NOTIFICATION_INFO.toBuilder().build()); + NotificationInfo bucketInfo = NOTIFICATION_INFO.toBuilder().setGeneratedId("id").build(); + assertEquals("id", bucketInfo.getGeneratedId()); + bucketInfo = bucketInfo.toBuilder().setGeneratedId(GENERATED_ID).build(); + compareBuckets(NOTIFICATION_INFO, bucketInfo); + } - @Test - public void testToBuilderIncomplete() { - NotificationInfo incompleteBucketInfo = NotificationInfo.newBuilder(TOPIC).build(); - compareBuckets(incompleteBucketInfo, incompleteBucketInfo.toBuilder().build()); - } + @Test + public void testToBuilderIncomplete() { + NotificationInfo incompleteBucketInfo = NotificationInfo.newBuilder(TOPIC).build(); + compareBuckets(incompleteBucketInfo, incompleteBucketInfo.toBuilder().build()); + } - @Test - public void testOf() { - NotificationInfo bucketInfo = NotificationInfo.of(TOPIC); - assertEquals(TOPIC, bucketInfo.getTopic()); - } + @Test + public void testOf() { + NotificationInfo bucketInfo = NotificationInfo.of(TOPIC); + assertEquals(TOPIC, bucketInfo.getTopic()); + } - @Test - public void testBuilder() { - assertEquals(ETAG, NOTIFICATION_INFO.getEtag()); - assertEquals(GENERATED_ID, NOTIFICATION_INFO.getGeneratedId()); - assertEquals(SELF_LINK, NOTIFICATION_INFO.getSelfLink()); - assertEquals(EVENT_TYPES, NOTIFICATION_INFO.getEventTypes()); - assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION_INFO.getObjectNamePrefix()); - assertEquals(PAYLOAD_FORMAT, NOTIFICATION_INFO.getPayloadFormat()); - assertEquals(TOPIC, NOTIFICATION_INFO.getTopic()); - assertEquals(CUSTOM_ATTRIBUTES, NOTIFICATION_INFO.getCustomAttributes()); - } + @Test + public void testBuilder() { + assertEquals(ETAG, NOTIFICATION_INFO.getEtag()); + assertEquals(GENERATED_ID, NOTIFICATION_INFO.getGeneratedId()); + assertEquals(SELF_LINK, NOTIFICATION_INFO.getSelfLink()); + assertEquals(EVENT_TYPES, NOTIFICATION_INFO.getEventTypes()); + assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION_INFO.getObjectNamePrefix()); + assertEquals(PAYLOAD_FORMAT, NOTIFICATION_INFO.getPayloadFormat()); + assertEquals(TOPIC, NOTIFICATION_INFO.getTopic()); + assertEquals(CUSTOM_ATTRIBUTES, NOTIFICATION_INFO.getCustomAttributes()); + } - @Test - public void testToPbAndFromPb() { - compareBuckets(NOTIFICATION_INFO, NotificationInfo.fromPb(NOTIFICATION_INFO.toPb())); - NotificationInfo bucketInfo = - NotificationInfo.of(TOPIC).toBuilder().setPayloadFormat(PayloadFormat.NONE).build(); - compareBuckets(bucketInfo, NotificationInfo.fromPb(bucketInfo.toPb())); - } + @Test + public void testToPbAndFromPb() { + compareBuckets(NOTIFICATION_INFO, NotificationInfo.fromPb(NOTIFICATION_INFO.toPb())); + NotificationInfo bucketInfo = + NotificationInfo.of(TOPIC).toBuilder().setPayloadFormat(PayloadFormat.NONE).build(); + compareBuckets(bucketInfo, NotificationInfo.fromPb(bucketInfo.toPb())); + } - private void compareBuckets(NotificationInfo expected, NotificationInfo value) { - assertEquals(expected, value); - assertEquals(expected.getGeneratedId(), value.getGeneratedId()); - assertEquals(expected.getCustomAttributes(), value.getCustomAttributes()); - assertEquals(expected.getEtag(), value.getEtag()); - assertEquals(expected.getSelfLink(), value.getSelfLink()); - assertEquals(expected.getEventTypes(), value.getEventTypes()); - assertEquals(expected.getObjectNamePrefix(), value.getObjectNamePrefix()); - assertEquals(expected.getPayloadFormat(), value.getPayloadFormat()); - assertEquals(expected.getTopic(), value.getTopic()); - } -} \ No newline at end of file + private void compareBuckets(NotificationInfo expected, NotificationInfo value) { + assertEquals(expected, value); + assertEquals(expected.getGeneratedId(), value.getGeneratedId()); + assertEquals(expected.getCustomAttributes(), value.getCustomAttributes()); + assertEquals(expected.getEtag(), value.getEtag()); + assertEquals(expected.getSelfLink(), value.getSelfLink()); + assertEquals(expected.getEventTypes(), value.getEventTypes()); + assertEquals(expected.getObjectNamePrefix(), value.getObjectNamePrefix()); + assertEquals(expected.getPayloadFormat(), value.getPayloadFormat()); + assertEquals(expected.getTopic(), value.getTopic()); + } +} diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java new file mode 100644 index 000000000..87f1a37b7 --- /dev/null +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java @@ -0,0 +1,129 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.storage; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createStrictMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.util.List; +import java.util.Map; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class NotificationTest { + + private static final String ETAG = "0xFF00"; + private static final String GENERATED_ID = "B/N:1"; + private static final String SELF_LINK = "http://storage/b/n"; + private static final List EVENT_TYPES = + ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); + private static final String OBJECT_NAME_PREFIX = "index.html"; + private static final NotificationInfo.PayloadFormat PAYLOAD_FORMAT = + NotificationInfo.PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final String TOPIC = "projects/myProject/topics/topic1"; + private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); + private static final NotificationInfo FULL_NOTIFICATION_INFO = + NotificationInfo.newBuilder(TOPIC) + .setEtag(ETAG) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setSelfLink(SELF_LINK) + .setEventTypes(EVENT_TYPES) + .setObjectNamePrefix(OBJECT_NAME_PREFIX) + .setPayloadFormat(PAYLOAD_FORMAT) + .setGeneratedId(GENERATED_ID) + .build(); + private static final NotificationInfo NOTIFICATION_INFO = + NotificationInfo.newBuilder(TOPIC).build(); + + private Storage storage; + private StorageOptions mockOptions = createMock(StorageOptions.class); + + @Before + public void setUp() { + storage = createStrictMock(Storage.class); + } + + @After + public void tearDown() { + verify(storage); + } + + @Test + public void testBuilder() { + expect(storage.getOptions()).andReturn(mockOptions).times(2); + replay(storage); + Notification.Builder builder = + new Notification.Builder( + new Notification(storage, new NotificationInfo.BuilderImpl(NOTIFICATION_INFO))); + Notification notification = + builder + .setEtag(ETAG) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setSelfLink(SELF_LINK) + .setEventTypes(EVENT_TYPES) + .setObjectNamePrefix(OBJECT_NAME_PREFIX) + .setPayloadFormat(PAYLOAD_FORMAT) + .setGeneratedId(GENERATED_ID) + .build(); + assertEquals(ETAG, notification.getEtag()); + assertEquals(GENERATED_ID, notification.getGeneratedId()); + assertEquals(SELF_LINK, notification.getSelfLink()); + assertEquals(EVENT_TYPES, notification.getEventTypes()); + assertEquals(OBJECT_NAME_PREFIX, notification.getObjectNamePrefix()); + assertEquals(PAYLOAD_FORMAT, notification.getPayloadFormat()); + assertEquals(TOPIC, notification.getTopic()); + assertEquals(CUSTOM_ATTRIBUTES, notification.getCustomAttributes()); + } + + @Test + public void testToBuilder() { + expect(storage.getOptions()).andReturn(mockOptions).times(2); + replay(storage); + Notification notification = + new Notification(storage, new NotificationInfo.BuilderImpl(FULL_NOTIFICATION_INFO)); + compareBuckets(notification, notification.toBuilder().build()); + } + + @Test + public void testFromPb() { + expect(storage.getOptions()).andReturn(mockOptions).times(1); + replay(storage); + compareBuckets( + FULL_NOTIFICATION_INFO, Notification.fromPb(storage, FULL_NOTIFICATION_INFO.toPb())); + } + + private void compareBuckets(NotificationInfo expected, NotificationInfo value) { + assertEquals(expected.getGeneratedId(), value.getGeneratedId()); + assertEquals(expected.getCustomAttributes(), value.getCustomAttributes()); + assertEquals(expected.getEtag(), value.getEtag()); + assertEquals(expected.getSelfLink(), value.getSelfLink()); + assertEquals(expected.getEventTypes(), value.getEventTypes()); + assertEquals(expected.getObjectNamePrefix(), value.getObjectNamePrefix()); + assertEquals(expected.getPayloadFormat(), value.getPayloadFormat()); + assertEquals(expected.getTopic().trim(), value.getTopic().trim()); + } +} diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java index 7fbbc8843..7ff8372fb 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java @@ -372,32 +372,32 @@ public long millisTime() { private static final String GENERATED_ID = "B/N:1"; private static final String SELF_LINK = "http://storage/b/n"; private static final List EVENT_TYPES = - ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); + ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); private static final String OBJECT_NAME_PREFIX = "index.html"; private static final NotificationInfo.PayloadFormat PAYLOAD_FORMAT = - NotificationInfo.PayloadFormat.JSON_API_V1.JSON_API_V1; + NotificationInfo.PayloadFormat.JSON_API_V1.JSON_API_V1; private static final String TOPIC = "projects/myProject/topics/topic1"; private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); private static final NotificationInfo NOTIFICATION_INFO_01 = - NotificationInfo.newBuilder(TOPIC) - .setEtag(ETAG) - .setCustomAttributes(CUSTOM_ATTRIBUTES) - .setSelfLink(SELF_LINK) - .setEventTypes(EVENT_TYPES) - .setObjectNamePrefix(OBJECT_NAME_PREFIX) - .setPayloadFormat(PAYLOAD_FORMAT) - .setGeneratedId(GENERATED_ID) - .build(); + NotificationInfo.newBuilder(TOPIC) + .setEtag(ETAG) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setSelfLink(SELF_LINK) + .setEventTypes(EVENT_TYPES) + .setObjectNamePrefix(OBJECT_NAME_PREFIX) + .setPayloadFormat(PAYLOAD_FORMAT) + .setGeneratedId(GENERATED_ID) + .build(); private static final NotificationInfo NOTIFICATION_INFO_02 = - NotificationInfo.newBuilder(TOPIC) - .setEtag(ETAG) - .setCustomAttributes(CUSTOM_ATTRIBUTES) - .setSelfLink(SELF_LINK) - .setEventTypes(EVENT_TYPES) - .setObjectNamePrefix(OBJECT_NAME_PREFIX) - .setPayloadFormat(PAYLOAD_FORMAT) - .setGeneratedId(GENERATED_ID) - .build(); + NotificationInfo.newBuilder(TOPIC) + .setEtag(ETAG) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setSelfLink(SELF_LINK) + .setEventTypes(EVENT_TYPES) + .setObjectNamePrefix(OBJECT_NAME_PREFIX) + .setPayloadFormat(PAYLOAD_FORMAT) + .setGeneratedId(GENERATED_ID) + .build(); private static final String ACCOUNT = "account"; private static PrivateKey privateKey; @@ -1676,23 +1676,22 @@ public void testWriterFailure() { assertSame(STORAGE_FAILURE, e.getCause()); } } + @Test public void testCreateNotification() { - Notification notification = NOTIFICATION_INFO_01.toPb(); - EasyMock.expect(storageRpcMock.createNotification(BUCKET_NAME1, notification)) - .andReturn(notification); - EasyMock.replay(storageRpcMock); + doReturn(NOTIFICATION_INFO_01.toPb()) + .when(storageRpcMock) + .createNotification(BUCKET_NAME1, NOTIFICATION_INFO_01.toPb()); initializeService(); - Notification remoteNotification = - storage.createNotification(BUCKET_NAME1, NOTIFICATION_INFO_01); - compareBucketsNotification(remoteNotification); + Notification notification = storage.createNotification(BUCKET_NAME1, NOTIFICATION_INFO_01); + compareBucketsNotification(notification); } @Test public void testGetNotification() { doReturn(NOTIFICATION_INFO_01.toPb()) - .when(storageRpcMock) - .getNotification(BUCKET_NAME1,GENERATED_ID); + .when(storageRpcMock) + .getNotification(BUCKET_NAME1, GENERATED_ID); initializeService(); Notification notification = storage.getNotification(BUCKET_NAME1, GENERATED_ID); compareBucketsNotification(notification); @@ -1701,8 +1700,8 @@ public void testGetNotification() { @Test public void testListNotification() { doReturn(Arrays.asList(NOTIFICATION_INFO_01.toPb(), NOTIFICATION_INFO_02.toPb())) - .when(storageRpcMock) - .listNotifications(BUCKET_NAME1); + .when(storageRpcMock) + .listNotifications(BUCKET_NAME1); initializeService(); List notifications = storage.listNotifications(BUCKET_NAME1); assertEquals(2, notifications.size()); @@ -1710,22 +1709,20 @@ public void testListNotification() { @Test public void testDeleteNotification() { - doReturn(true) - .when(storageRpcMock) - .deleteNotification(BUCKET_NAME1, GENERATED_ID); + doReturn(true).when(storageRpcMock).deleteNotification(BUCKET_NAME1, GENERATED_ID); initializeService(); Boolean isDeleted = storage.deleteNotification(BUCKET_NAME1, GENERATED_ID); assertEquals(isDeleted, Boolean.TRUE); } private void compareBucketsNotification(Notification value) { - assertEquals(GENERATED_ID, value.getId()); + assertEquals(GENERATED_ID, value.getGeneratedId()); assertEquals(CUSTOM_ATTRIBUTES, value.getCustomAttributes()); assertEquals(ETAG, value.getEtag()); assertEquals(SELF_LINK, value.getSelfLink()); assertEquals(EVENT_TYPES, value.getEventTypes()); assertEquals(OBJECT_NAME_PREFIX, value.getObjectNamePrefix()); - assertEquals(PAYLOAD_FORMAT.name(), value.getPayloadFormat()); + assertEquals(PAYLOAD_FORMAT.name(), value.getPayloadFormat().name()); assertEquals(TOPIC, value.getTopic()); } } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index e9fa10a1c..af8e47d3e 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -41,6 +41,7 @@ import com.google.cloud.Policy; import com.google.cloud.ReadChannel; import com.google.cloud.RestorableState; +import com.google.cloud.ServiceOptions; import com.google.cloud.TransportOptions; import com.google.cloud.WriteChannel; import com.google.cloud.http.HttpTransportOptions; @@ -54,6 +55,7 @@ import com.google.cloud.kms.v1.KeyManagementServiceGrpc.KeyManagementServiceBlockingStub; import com.google.cloud.kms.v1.KeyRingName; import com.google.cloud.kms.v1.LocationName; +import com.google.cloud.pubsub.v1.TopicAdminClient; import com.google.cloud.storage.Acl; import com.google.cloud.storage.Acl.Role; import com.google.cloud.storage.Acl.User; @@ -71,6 +73,8 @@ import com.google.cloud.storage.HmacKey; import com.google.cloud.storage.HmacKey.HmacKeyState; import com.google.cloud.storage.HttpMethod; +import com.google.cloud.storage.Notification; +import com.google.cloud.storage.NotificationInfo; import com.google.cloud.storage.PostPolicyV4; import com.google.cloud.storage.PostPolicyV4.PostFieldsV4; import com.google.cloud.storage.Rpo; @@ -99,6 +103,7 @@ import com.google.common.reflect.AbstractInvocationHandler; import com.google.common.reflect.Reflection; import com.google.iam.v1.Binding; +import com.google.iam.v1.GetIamPolicyRequest; import com.google.iam.v1.IAMPolicyGrpc; import com.google.iam.v1.SetIamPolicyRequest; import io.grpc.ManagedChannel; @@ -132,6 +137,7 @@ import java.util.Map; import java.util.Random; import java.util.Set; +import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -162,6 +168,8 @@ public class ITStorageTest { private static RemoteStorageHelper remoteStorageHelper; private static Storage storage; + private static Notification notification; + private static TopicAdminClient topicAdminClient; private static String kmsKeyOneResourcePath; private static String kmsKeyTwoResourcePath; private static Metadata requestParamsHeader = new Metadata(); @@ -219,6 +227,13 @@ public class ITStorageTest { @Rule public final TestName testName = new TestName(); @Rule public final DataGeneration dataGeneration = new DataGeneration(new Random(1234567890)); + private static final String PROJECT = ServiceOptions.getDefaultProjectId(); + private static final String ID = UUID.randomUUID().toString().substring(0, 8); + private static final String TOPIC = + String.format("projects/%s/topics/test_topic_foo_%s", PROJECT, ID); + private static final NotificationInfo.PayloadFormat PAYLOAD_FORMAT = + NotificationInfo.PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); @BeforeClass public static void beforeClass() throws IOException { @@ -239,6 +254,10 @@ public static void beforeClass() throws IOException { // Prepare KMS KeyRing for CMEK tests prepareKmsKeys(); + + // Create notification. + topicAdminClient = TopicAdminClient.create(); + createNotification(topicAdminClient); } private static void unsetRequesterPays() { @@ -260,6 +279,11 @@ private static void unsetRequesterPays() { @AfterClass public static void afterClass() throws ExecutionException, InterruptedException { if (storage != null) { + + /* Delete the specified notification on the specified bucket as well as delete the pubsub topic */ + if (topicAdminClient != null) { + deleteNotification(topicAdminClient); + } // In beforeClass, we make buckets auto-delete blobs older than a day old. // Here, delete all buckets older than 2 days. They should already be empty and easy. long cleanTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(2); @@ -415,6 +439,36 @@ private static String ensureKmsKeyExistsForTests( return kmsKeyResourcePath; } + private static Notification createNotification(TopicAdminClient topicAdminClient) { + topicAdminClient.createTopic(TOPIC); + GetIamPolicyRequest getIamPolicyRequest = + GetIamPolicyRequest.newBuilder().setResource(TOPIC).build(); + com.google.iam.v1.Policy policy = topicAdminClient.getIamPolicy(getIamPolicyRequest); + Binding binding = + Binding.newBuilder().setRole("roles/owner").addMembers("allAuthenticatedUsers").build(); + SetIamPolicyRequest setIamPolicyRequest = + SetIamPolicyRequest.newBuilder() + .setResource(TOPIC) + .setPolicy(policy.toBuilder().addBindings(binding).build()) + .build(); + topicAdminClient.setIamPolicy(setIamPolicyRequest); + + // Create a notification on a bucket. + NotificationInfo notificationInfo = + NotificationInfo.newBuilder(TOPIC) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setPayloadFormat(PAYLOAD_FORMAT) + .build(); + notification = storage.createNotification(BUCKET, notificationInfo); + return notification; + } + + public static void deleteNotification(TopicAdminClient topicAdminClient) { + storage.deleteNotification(BUCKET, notification.getGeneratedId()); + topicAdminClient.deleteTopic(TOPIC); + topicAdminClient.close(); + } + @Test(timeout = 5000) public void testListBuckets() throws InterruptedException { Iterator bucketIterator = @@ -3768,23 +3822,44 @@ public void testRemoveBucketCORS() throws ExecutionException, InterruptedExcepti @Test public void testBucketUpdateTime() throws ExecutionException, InterruptedException { - String bucketName = RemoteStorageHelper.generateBucketName(); - BucketInfo bucketInfo = - BucketInfo.newBuilder(bucketName).setLocation("us").setVersioningEnabled(true).build(); - try { - Bucket bucket = storage.create(bucketInfo); - assertThat(bucket).isNotNull(); - assertThat(bucket.versioningEnabled()).isTrue(); - assertThat(bucket.getCreateTime()).isNotNull(); - assertThat(bucket.getUpdateTime()).isEqualTo(bucket.getCreateTime()); - - Bucket updatedBucket = bucket.toBuilder().setVersioningEnabled(false).build().update(); - assertThat(updatedBucket.versioningEnabled()).isFalse(); - assertThat(updatedBucket.getUpdateTime()).isNotNull(); - assertThat(updatedBucket.getCreateTime()).isEqualTo(bucket.getCreateTime()); - assertThat(updatedBucket.getUpdateTime()).isGreaterThan(bucket.getCreateTime()); - } finally { - RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); + String bucketName = RemoteStorageHelper.generateBucketName(); + BucketInfo bucketInfo = + BucketInfo.newBuilder(bucketName).setLocation("us").setVersioningEnabled(true).build(); + try { + Bucket bucket = storage.create(bucketInfo); + assertThat(bucket).isNotNull(); + assertThat(bucket.versioningEnabled()).isTrue(); + assertThat(bucket.getCreateTime()).isNotNull(); + assertThat(bucket.getUpdateTime()).isEqualTo(bucket.getCreateTime()); + + Bucket updatedBucket = bucket.toBuilder().setVersioningEnabled(false).build().update(); + assertThat(updatedBucket.versioningEnabled()).isFalse(); + assertThat(updatedBucket.getUpdateTime()).isNotNull(); + assertThat(updatedBucket.getCreateTime()).isEqualTo(bucket.getCreateTime()); + assertThat(updatedBucket.getUpdateTime()).isGreaterThan(bucket.getCreateTime()); + } finally { + RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); + } + } + + @Test + public void testGetNotification() { + Notification actualNotification = + storage.getNotification(BUCKET, notification.getGeneratedId()); + assertEquals(CUSTOM_ATTRIBUTES, actualNotification.getCustomAttributes()); + assertEquals(PAYLOAD_FORMAT.name(), actualNotification.getPayloadFormat().name()); + assertTrue(actualNotification.getTopic().contains(TOPIC)); + } + + @Test + public void testListNotification() { + List notifications = storage.listNotifications(BUCKET); + for (Notification actualNotification : notifications) { + if (actualNotification.getGeneratedId().equals(notification.getGeneratedId())) { + assertEquals(CUSTOM_ATTRIBUTES, actualNotification.getCustomAttributes()); + assertEquals(PAYLOAD_FORMAT.name(), actualNotification.getPayloadFormat().name()); + assertTrue(actualNotification.getTopic().contains(TOPIC)); + } } } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/StorageRpcTestBaseTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/StorageRpcTestBaseTest.java index affd6fb5c..7feef9f18 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/StorageRpcTestBaseTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/testing/StorageRpcTestBaseTest.java @@ -577,16 +577,16 @@ public Notification call() { }; } - @Test - public void testGetNotification() { - rpc = - new Callable() { - @Override - public Notification call() { - return STORAGE_RPC.getNotification("bucket", "notification"); - } - }; - } + @Test + public void testGetNotification() { + rpc = + new Callable() { + @Override + public Notification call() { + return STORAGE_RPC.getNotification("bucket", "notification"); + } + }; + } @Test public void testLockRetentionPolicy() { diff --git a/pom.xml b/pom.xml index 321877adb..4fad76dfb 100644 --- a/pom.xml +++ b/pom.xml @@ -77,6 +77,12 @@ google-api-services-storage v1-rev20220210-1.32.1 + + com.google.cloud + google-cloud-pubsub + 1.106.0 + test + org.easymock easymock From 8489ff2c0d6ffab4cac305e0104263d883d58689 Mon Sep 17 00:00:00 2001 From: athakor Date: Thu, 2 Jul 2020 15:26:52 +0530 Subject: [PATCH 03/18] feat: simplified the code and fixed the review changes --- .../clirr-ignored-differences.xml | 2 +- .../google/cloud/storage/Notification.java | 286 ++++++++++++--- .../cloud/storage/NotificationInfo.java | 342 ------------------ .../com/google/cloud/storage/Storage.java | 23 +- .../com/google/cloud/storage/StorageImpl.java | 21 +- .../cloud/storage/spi/v1/StorageRpc.java | 10 +- .../cloud/storage/NotificationInfoTest.java | 102 ------ .../cloud/storage/NotificationTest.java | 112 +++--- .../cloud/storage/StorageImplMockitoTest.java | 22 +- .../cloud/storage/it/ITStorageTest.java | 11 +- 10 files changed, 315 insertions(+), 616 deletions(-) delete mode 100644 google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java delete mode 100644 google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml index 9f137f62c..04d2052ad 100644 --- a/google-cloud-storage/clirr-ignored-differences.xml +++ b/google-cloud-storage/clirr-ignored-differences.xml @@ -13,7 +13,7 @@ com/google/cloud/storage/Storage - com.google.cloud.storage.Notification createNotification(java.lang.String, com.google.cloud.storage.NotificationInfo) + com.google.cloud.storage.Notification createNotification(java.lang.String, com.google.cloud.storage.Notification) 7012 diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java index 33532f558..78a5dcc79 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -13,127 +13,301 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.google.cloud.storage; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.api.pathtemplate.PathTemplate; +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import java.io.Serializable; +import java.util.List; import java.util.Map; import java.util.Objects; /** - * Google Storage Notification object; + * Google Storage Notification metadata; * - * @see notifications + * @see Concepts and + * Terminology */ -public class Notification extends NotificationInfo { +public class Notification implements Serializable { + + private static final long serialVersionUID = 5725883368559753810L; + private static final PathTemplate PATH_TEMPLATE = + PathTemplate.createWithoutUrlEncoding("projects/{project}/topics/{topic}"); + + public enum PayloadFormat { + JSON_API_V1, + NONE + } + + static final Function + FROM_PB_FUNCTION = + new Function() { + @Override + public Notification apply(com.google.api.services.storage.model.Notification pb) { + return Notification.fromPb(pb); + } + }; + static final Function + TO_PB_FUNCTION = + new Function() { + @Override + public com.google.api.services.storage.model.Notification apply( + Notification notification) { + return notification.toPb(); + } + }; + private final String generatedId; + private final String topic; + private final List eventTypes; + private final Map customAttributes; + private final PayloadFormat payloadFormat; + private final String objectNamePrefix; + private final String etag; + private final String selfLink; + + /** Builder for {@code NotificatioInfo}. */ + public static class Builder { - private final StorageOptions options; - private transient Storage storage; + private String generatedId; + private String topic; + private List eventTypes; + private Map customAttributes; + private PayloadFormat payloadFormat; + private String objectNamePrefix; + private String etag; + private String selfLink; - /** Builder for {@code Notification}. */ - public static class Builder extends NotificationInfo.Builder { - private final Storage storage; - private final NotificationInfo.BuilderImpl infoBuilder; + private Builder(String topic) { + this.topic = topic; + } - Builder(Notification notification) { - this.storage = notification.storage; - this.infoBuilder = new NotificationInfo.BuilderImpl(notification); + private Builder(Notification notification) { + generatedId = notification.generatedId; + etag = notification.etag; + selfLink = notification.selfLink; + topic = notification.topic; + eventTypes = notification.eventTypes; + customAttributes = notification.customAttributes; + payloadFormat = notification.payloadFormat; + objectNamePrefix = notification.objectNamePrefix; } - @Override public Builder setGeneratedId(String generatedId) { - infoBuilder.setGeneratedId(generatedId); + this.generatedId = generatedId; return this; } - @Override public Builder setSelfLink(String selfLink) { - infoBuilder.setSelfLink(selfLink); + this.selfLink = selfLink; return this; } - @Override + /** The name of the topic. It must have the format "projects/{project}/topics/{topic}". */ public Builder setTopic(String topic) { - infoBuilder.setTopic(topic); + this.topic = topic; return this; } - @Override public Builder setPayloadFormat(PayloadFormat payloadFormat) { - infoBuilder.setPayloadFormat(payloadFormat); + this.payloadFormat = payloadFormat; return this; } - @Override public Builder setObjectNamePrefix(String objectNamePrefix) { - infoBuilder.setObjectNamePrefix(objectNamePrefix); + this.objectNamePrefix = objectNamePrefix; return this; } - @Override public Builder setEventTypes(Iterable eventTypes) { - infoBuilder.setEventTypes(eventTypes); + this.eventTypes = eventTypes != null ? ImmutableList.copyOf(eventTypes) : null; return this; } - @Override public Builder setEtag(String etag) { - infoBuilder.setEtag(etag); + this.etag = etag; return this; } - @Override public Builder setCustomAttributes(Map customAttributes) { - infoBuilder.setCustomAttributes(customAttributes); + this.customAttributes = + customAttributes != null ? ImmutableMap.copyOf(customAttributes) : null; return this; } - @Override public Notification build() { - return new Notification(storage, infoBuilder); + checkNotNull(topic); + return new Notification(this); } } - Notification(Storage storage, NotificationInfo.BuilderImpl infoBuilder) { - super(infoBuilder); - this.storage = checkNotNull(storage); - this.options = storage.getOptions(); + private Notification(Builder builder) { + generatedId = builder.generatedId; + etag = builder.etag; + selfLink = builder.selfLink; + topic = builder.topic; + eventTypes = builder.eventTypes; + customAttributes = builder.customAttributes; + payloadFormat = builder.payloadFormat; + objectNamePrefix = builder.objectNamePrefix; + } + + /** Returns the service-generated id for the notification. */ + public String getGeneratedId() { + return generatedId; } - /** Returns the notification's {@code Storage} object used to issue requests. */ - public Storage getStorage() { - return storage; + /** Returns the topic to which this subscription publishes. */ + public String getTopic() { + return topic; + } + + /** Returns the canonical URI of this topic as a string. */ + public String getSelfLink() { + return selfLink; + } + + /** Returns the desired content of the Payload. */ + public PayloadFormat getPayloadFormat() { + return payloadFormat; + } + + /** Returns the object name prefix for which this notification configuration applies. */ + public String getObjectNamePrefix() { + return objectNamePrefix; + } + + /** + * Returns HTTP 1.1 Entity tag for the notification. + * + * @see Entity Tags + */ + public String getEtag() { + return etag; + } + + /** + * Returns the list of event types that this notification will apply to. If empty, notifications + * will be sent on all event types. + * + * @see Cross-Origin Resource Sharing + * (CORS) + */ + public List getEventTypes() { + return eventTypes; + } + + /** + * Returns the list of additional attributes to attach to each Cloud PubSub message published for + * this notification subscription. + * + * @see + * About Access Control Lists + */ + public Map getCustomAttributes() { + return customAttributes; } @Override - public Builder toBuilder() { - return new Notification.Builder(this); + public int hashCode() { + return Objects.hash(getTopic()); } @Override - public boolean equals(Object o) { - if (this == o) { - return true; + public boolean equals(Object obj) { + return obj == this + || obj != null + && obj.getClass().equals(Notification.class) + && Objects.equals(toPb(), ((Notification) obj).toPb()); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("topic", getTopic()).toString(); + } + + com.google.api.services.storage.model.Notification toPb() { + com.google.api.services.storage.model.Notification notificationPb = + new com.google.api.services.storage.model.Notification(); + notificationPb.setId(generatedId); + notificationPb.setEtag(etag); + if (customAttributes != null) { + notificationPb.setCustomAttributes(customAttributes); + } + if (eventTypes != null) { + notificationPb.setEventTypes(eventTypes); } - if (o == null || getClass() != o.getClass()) { - return false; + if (objectNamePrefix != null) { + notificationPb.setObjectNamePrefix(objectNamePrefix); } - if (!super.equals(o)) { - return false; + if (payloadFormat != null) { + notificationPb.setPayloadFormat(payloadFormat.toString()); + } else { + notificationPb.setPayloadFormat(PayloadFormat.NONE.toString()); } - Notification that = (Notification) o; - return Objects.equals(toPb(), that.toPb()) && Objects.equals(options, that.options); + notificationPb.setSelfLink(selfLink); + notificationPb.setTopic(topic); + + return notificationPb; } - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), options, storage); + /** + * Creates a {@code Notification} object for the provided topic name. + * + * @param topic The name of the topic. It must have the format + * "projects/{project}/topics/{topic}". + */ + public static Notification of(String topic) { + PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); + return newBuilder(topic).build(); + } + + /** Returns a builder for the current notification. */ + public Builder toBuilder() { + return new Builder(this); + } + + /** + * Returns a {@code Notification} builder where the topic's name is set to the provided name. + * + * @param topic The name of the topic. It must have the format + * "projects/{project}/topics/{topic}". + */ + public static Builder newBuilder(String topic) { + PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); + return new Builder(topic); } - static Notification fromPb( - Storage storage, com.google.api.services.storage.model.Notification notificationPb) { - return new Notification( - storage, new NotificationInfo.BuilderImpl(NotificationInfo.fromPb(notificationPb))); + static Notification fromPb(com.google.api.services.storage.model.Notification notificationPb) { + Builder builder = newBuilder(notificationPb.getTopic()); + if (notificationPb.getId() != null) { + builder.setGeneratedId(notificationPb.getId()); + } + if (notificationPb.getEtag() != null) { + builder.setEtag(notificationPb.getEtag()); + } + if (notificationPb.getCustomAttributes() != null) { + builder.setCustomAttributes(notificationPb.getCustomAttributes()); + } + if (notificationPb.getSelfLink() != null) { + builder.setSelfLink(notificationPb.getSelfLink()); + } + if (notificationPb.getObjectNamePrefix() != null) { + builder.setObjectNamePrefix(notificationPb.getObjectNamePrefix()); + } + if (notificationPb.getTopic() != null) { + builder.setTopic(notificationPb.getTopic()); + } + if (notificationPb.getEventTypes() != null) { + builder.setEventTypes(notificationPb.getEventTypes()); + } + if (notificationPb.getPayloadFormat() != null) { + builder.setPayloadFormat(PayloadFormat.valueOf(notificationPb.getPayloadFormat())); + } + return builder.build(); } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java deleted file mode 100644 index d9653fec7..000000000 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.cloud.storage; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.api.pathtemplate.PathTemplate; -import com.google.api.services.storage.model.Notification; -import com.google.common.base.Function; -import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * Google Storage Notification metadata; - * - * @see Concepts and - * Terminology - */ -public class NotificationInfo implements Serializable { - - private static final long serialVersionUID = 5725883368559753810L; - private static final PathTemplate PATH_TEMPLATE = - PathTemplate.createWithoutUrlEncoding("projects/{project}/topics/{topic}"); - - public enum PayloadFormat { - JSON_API_V1, - NONE - } - - static final Function FROM_PB_FUNCTION = - new Function() { - @Override - public NotificationInfo apply(Notification pb) { - return NotificationInfo.fromPb(pb); - } - }; - static final Function TO_PB_FUNCTION = - new Function() { - @Override - public Notification apply(NotificationInfo NotificationInfo) { - return NotificationInfo.toPb(); - } - }; - private final String generatedId; - private final String topic; - private final List eventTypes; - private final Map customAttributes; - private final PayloadFormat payloadFormat; - private final String objectNamePrefix; - private final String etag; - private final String selfLink; - - /** Builder for {@code NotificatioInfo}. */ - public abstract static class Builder { - Builder() {} - - public abstract Builder setGeneratedId(String generatedId); - - public abstract Builder setSelfLink(String selfLink); - - public abstract Builder setTopic(String topic); - - public abstract Builder setPayloadFormat(PayloadFormat payloadFormat); - - public abstract Builder setObjectNamePrefix(String objectNamePrefix); - - public abstract Builder setEventTypes(Iterable eventTypes); - - public abstract Builder setEtag(String etag); - - public abstract Builder setCustomAttributes(Map customAttributes); - - /** Creates a {@code NotificationInfo} object. */ - public abstract NotificationInfo build(); - } - - public static final class BuilderImpl extends Builder { - - private String generatedId; - private String topic; - private List eventTypes; - private Map customAttributes; - private PayloadFormat payloadFormat; - private String objectNamePrefix; - private String etag; - private String selfLink; - - BuilderImpl(String topic) { - this.topic = topic; - } - - BuilderImpl(NotificationInfo NotificationInfo) { - generatedId = NotificationInfo.generatedId; - etag = NotificationInfo.etag; - selfLink = NotificationInfo.selfLink; - topic = NotificationInfo.topic; - eventTypes = NotificationInfo.eventTypes; - customAttributes = NotificationInfo.customAttributes; - payloadFormat = NotificationInfo.payloadFormat; - objectNamePrefix = NotificationInfo.objectNamePrefix; - } - - @Override - public Builder setGeneratedId(String generatedId) { - this.generatedId = generatedId; - return this; - } - - @Override - public Builder setSelfLink(String selfLink) { - this.selfLink = selfLink; - return this; - } - - /** The name of the topic. It must have the format "projects/{project}/topics/{topic}". */ - @Override - public Builder setTopic(String topic) { - this.topic = topic; - return this; - } - - @Override - public Builder setPayloadFormat(PayloadFormat payloadFormat) { - this.payloadFormat = payloadFormat; - return this; - } - - @Override - public Builder setObjectNamePrefix(String objectNamePrefix) { - this.objectNamePrefix = objectNamePrefix; - return this; - } - - @Override - public Builder setEventTypes(Iterable eventTypes) { - this.eventTypes = eventTypes != null ? ImmutableList.copyOf(eventTypes) : null; - return this; - } - - @Override - public Builder setEtag(String etag) { - this.etag = etag; - return this; - } - - @Override - public Builder setCustomAttributes(Map customAttributes) { - this.customAttributes = - customAttributes != null ? ImmutableMap.copyOf(customAttributes) : null; - return this; - } - - @Override - public NotificationInfo build() { - checkNotNull(topic); - return new NotificationInfo(this); - } - } - - NotificationInfo(BuilderImpl builder) { - generatedId = builder.generatedId; - etag = builder.etag; - selfLink = builder.selfLink; - topic = builder.topic; - eventTypes = builder.eventTypes; - customAttributes = builder.customAttributes; - payloadFormat = builder.payloadFormat; - objectNamePrefix = builder.objectNamePrefix; - } - - /** Returns the service-generated id for the notification. */ - public String getGeneratedId() { - return generatedId; - } - - /** Returns the topic to which this subscription publishes. */ - public String getTopic() { - return topic; - } - - /** Returns the canonical URI of this topic as a string. */ - public String getSelfLink() { - return selfLink; - } - - /** Returns the desired content of the Payload. */ - public PayloadFormat getPayloadFormat() { - return payloadFormat; - } - - /** Returns the object name prefix for which this notification configuration applies. */ - public String getObjectNamePrefix() { - return objectNamePrefix; - } - - /** - * Returns HTTP 1.1 Entity tag for the notification. - * - * @see Entity Tags - */ - public String getEtag() { - return etag; - } - - /** - * Returns the list of event types that this notification will apply to. If empty, notifications - * will be sent on all event types. - * - * @see Cross-Origin Resource Sharing - * (CORS) - */ - public List getEventTypes() { - return eventTypes; - } - - /** - * Returns the list of additional attributes to attach to each Cloud PubSub message published for - * this notification subscription. - * - * @see - * About Access Control Lists - */ - public Map getCustomAttributes() { - return customAttributes; - } - - /** Returns a builder for the current notification. */ - public Builder toBuilder() { - return new BuilderImpl(this); - } - - @Override - public int hashCode() { - return Objects.hash(getTopic()); - } - - @Override - public boolean equals(Object obj) { - return obj == this - || obj != null - && obj.getClass().equals(NotificationInfo.class) - && Objects.equals(toPb(), ((NotificationInfo) obj).toPb()); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this).add("topic", getTopic()).toString(); - } - - Notification toPb() { - Notification notificationPb = new Notification(); - notificationPb.setId(generatedId); - notificationPb.setEtag(etag); - if (customAttributes != null) { - notificationPb.setCustomAttributes(customAttributes); - } - if (eventTypes != null) { - notificationPb.setEventTypes(eventTypes); - } - if (objectNamePrefix != null) { - notificationPb.setObjectNamePrefix(objectNamePrefix); - } - if (payloadFormat != null) { - notificationPb.setPayloadFormat(payloadFormat.toString()); - } else { - notificationPb.setPayloadFormat(PayloadFormat.NONE.toString()); - } - notificationPb.setSelfLink(selfLink); - notificationPb.setTopic(topic); - - return notificationPb; - } - - /** - * Creates a {@code NotificationInfo} object for the provided topic name. - * - * @param topic The name of the topic. It must have the format - * "projects/{project}/topics/{topic}". - */ - public static NotificationInfo of(String topic) { - PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); - return newBuilder(topic).build(); - } - - /** - * Returns a {@code NotificationInfo} builder where the topic's name is set to the provided name. - * - * @param topic The name of the topic. It must have the format - * "projects/{project}/topics/{topic}". - */ - public static Builder newBuilder(String topic) { - PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); - return new BuilderImpl(topic); - } - - static NotificationInfo fromPb(Notification notificationPb) { - Builder builder = newBuilder(notificationPb.getTopic()); - if (notificationPb.getId() != null) { - builder.setGeneratedId(notificationPb.getId()); - } - if (notificationPb.getEtag() != null) { - builder.setEtag(notificationPb.getEtag()); - } - if (notificationPb.getCustomAttributes() != null) { - builder.setCustomAttributes(notificationPb.getCustomAttributes()); - } - if (notificationPb.getSelfLink() != null) { - builder.setSelfLink(notificationPb.getSelfLink()); - } - if (notificationPb.getObjectNamePrefix() != null) { - builder.setObjectNamePrefix(notificationPb.getObjectNamePrefix()); - } - if (notificationPb.getTopic() != null) { - builder.setTopic(notificationPb.getTopic()); - } - if (notificationPb.getEventTypes() != null) { - builder.setEventTypes(notificationPb.getEventTypes()); - } - if (notificationPb.getPayloadFormat() != null) { - builder.setPayloadFormat(PayloadFormat.valueOf(notificationPb.getPayloadFormat())); - } - return builder.build(); - } -} diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index d0cc60518..34761ef90 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3627,33 +3627,40 @@ List testIamPermissions( ServiceAccount getServiceAccount(String projectId); /** - * Creates a notification with the specified entity on the specified bucket. + * Creates a notification subscription for a given bucket. * - * @return the notification that was created. + * @param bucket name of the bucket + * @param notification a {@code Notification} object + * @return the notification that was created * @throws StorageException upon failure */ - Notification createNotification(String bucket, NotificationInfo notificationInfo); + Notification createNotification(String bucket, Notification notification); /** - * Get the notification with the specified name on the specified object. + * Gets the notification with the specified name on the bucket. * - * @return the notification object that exist on the bucket. + * @param bucket name of the bucket + * @param notification notification ID + * @return the notification object that exist on the bucket or {@code null} if not found * @throws StorageException upon failure */ Notification getNotification(String bucket, String notification); /** - * List the notifications for the provided bucket. + * Retrieves a list of notification subscriptions for a given bucket. * + * @param bucket name of the bucket * @return a list of {@link Notification} objects that exist on the bucket. * @throws StorageException upon failure */ List listNotifications(String bucket); /** - * Deletes the notification with the specified name on the specified object. + * Deletes the notification subscription with the specified name on the bucket. * - * @return {@code true} if the notification was deleted, {@code false} if it was not found + * @param bucket name of the bucket + * @param notification ID of the notification to delete + * @return {@code true} if the notification has been deleted, {@code false} if not found * @throws StorageException upon failure */ boolean deleteNotification(String bucket, String notification); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index a4345e572..1cbf2957d 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -1375,13 +1375,10 @@ private U run(ResultRetryAlgorithm algorithm, Callable c, Function< } @Override - public Notification createNotification( - final String bucket, final NotificationInfo notificationInfo) { - final com.google.api.services.storage.model.Notification notificationPb = - notificationInfo.toPb(); + public Notification createNotification(final String bucket, final Notification notification) { + final com.google.api.services.storage.model.Notification notificationPb = notification.toPb(); try { return Notification.fromPb( - this, runWithRetries( new Callable() { @Override @@ -1411,7 +1408,7 @@ public com.google.api.services.storage.model.Notification call() { getOptions().getRetrySettings(), EXCEPTION_HANDLER, getOptions().getClock()); - return answer == null ? null : Notification.fromPb(this, answer); + return answer == null ? null : Notification.fromPb(answer); } catch (RetryHelperException e) { throw StorageException.translateAndThrow(e); } @@ -1431,17 +1428,7 @@ public List call() { getOptions().getRetrySettings(), EXCEPTION_HANDLER, getOptions().getClock()); - return answer == null - ? null - : Lists.transform( - answer, - new Function() { - @Override - public Notification apply( - com.google.api.services.storage.model.Notification notificationPb) { - return Notification.fromPb(getOptions().getService(), notificationPb); - } - }); + return Lists.transform(answer, Notification.FROM_PB_FUNCTION); } catch (RetryHelperException e) { throw StorageException.translateAndThrow(e); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java index f9fbb1b51..932c11581 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java @@ -561,15 +561,15 @@ TestIamPermissionsResponse testIamPermissions( String bucket, List permissions, Map options); /** - * Deletes the notification with the specified name on the specified object. + * Deletes the notification subscription with the specified name on the bucket. * - * @return {@code true} if the notification was deleted, {@code false} if it was not found + * @return {@code true} if the notification has been deleted, {@code false} if not found * @throws StorageException upon failure */ boolean deleteNotification(String bucket, String notification); /** - * List the notifications for the provided bucket. + * Retrieves a list of notification subscriptions for a given bucket. * * @return a list of {@link Notification} objects that exist on the bucket. * @throws StorageException upon failure @@ -577,7 +577,7 @@ TestIamPermissionsResponse testIamPermissions( List listNotifications(String bucket); /** - * Creates a notification with the specified entity on the specified bucket. + * Creates a notification subscription for a given bucket. * * @return the notification that was created. * @throws StorageException upon failure @@ -585,7 +585,7 @@ TestIamPermissionsResponse testIamPermissions( Notification createNotification(String bucket, Notification notification); /** - * Get the notification with the specified name on the specified object. + * Gets the notification with the specified name on the bucket. * * @return the notification object that exist on the bucket. * @throws StorageException upon failure diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java deleted file mode 100644 index 40b8a5ccf..000000000 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.cloud.storage; - -import static org.junit.Assert.assertEquals; - -import com.google.cloud.storage.NotificationInfo.PayloadFormat; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import java.util.List; -import java.util.Map; -import org.junit.Test; - -public class NotificationInfoTest { - - private static final String ETAG = "0xFF00"; - private static final String GENERATED_ID = "B/N:1"; - private static final String SELF_LINK = "http://storage/b/n"; - private static final List EVENT_TYPES = - ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); - private static final String OBJECT_NAME_PREFIX = "index.html"; - private static final PayloadFormat PAYLOAD_FORMAT = PayloadFormat.JSON_API_V1.JSON_API_V1; - private static final String TOPIC = "projects/myProject/topics/topic1"; - private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); - private static final NotificationInfo NOTIFICATION_INFO = - NotificationInfo.newBuilder(TOPIC) - .setEtag(ETAG) - .setCustomAttributes(CUSTOM_ATTRIBUTES) - .setSelfLink(SELF_LINK) - .setEventTypes(EVENT_TYPES) - .setObjectNamePrefix(OBJECT_NAME_PREFIX) - .setPayloadFormat(PAYLOAD_FORMAT) - .setGeneratedId(GENERATED_ID) - .build(); - - @Test - public void testToBuilder() { - compareBuckets(NOTIFICATION_INFO, NOTIFICATION_INFO.toBuilder().build()); - NotificationInfo bucketInfo = NOTIFICATION_INFO.toBuilder().setGeneratedId("id").build(); - assertEquals("id", bucketInfo.getGeneratedId()); - bucketInfo = bucketInfo.toBuilder().setGeneratedId(GENERATED_ID).build(); - compareBuckets(NOTIFICATION_INFO, bucketInfo); - } - - @Test - public void testToBuilderIncomplete() { - NotificationInfo incompleteBucketInfo = NotificationInfo.newBuilder(TOPIC).build(); - compareBuckets(incompleteBucketInfo, incompleteBucketInfo.toBuilder().build()); - } - - @Test - public void testOf() { - NotificationInfo bucketInfo = NotificationInfo.of(TOPIC); - assertEquals(TOPIC, bucketInfo.getTopic()); - } - - @Test - public void testBuilder() { - assertEquals(ETAG, NOTIFICATION_INFO.getEtag()); - assertEquals(GENERATED_ID, NOTIFICATION_INFO.getGeneratedId()); - assertEquals(SELF_LINK, NOTIFICATION_INFO.getSelfLink()); - assertEquals(EVENT_TYPES, NOTIFICATION_INFO.getEventTypes()); - assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION_INFO.getObjectNamePrefix()); - assertEquals(PAYLOAD_FORMAT, NOTIFICATION_INFO.getPayloadFormat()); - assertEquals(TOPIC, NOTIFICATION_INFO.getTopic()); - assertEquals(CUSTOM_ATTRIBUTES, NOTIFICATION_INFO.getCustomAttributes()); - } - - @Test - public void testToPbAndFromPb() { - compareBuckets(NOTIFICATION_INFO, NotificationInfo.fromPb(NOTIFICATION_INFO.toPb())); - NotificationInfo bucketInfo = - NotificationInfo.of(TOPIC).toBuilder().setPayloadFormat(PayloadFormat.NONE).build(); - compareBuckets(bucketInfo, NotificationInfo.fromPb(bucketInfo.toPb())); - } - - private void compareBuckets(NotificationInfo expected, NotificationInfo value) { - assertEquals(expected, value); - assertEquals(expected.getGeneratedId(), value.getGeneratedId()); - assertEquals(expected.getCustomAttributes(), value.getCustomAttributes()); - assertEquals(expected.getEtag(), value.getEtag()); - assertEquals(expected.getSelfLink(), value.getSelfLink()); - assertEquals(expected.getEventTypes(), value.getEventTypes()); - assertEquals(expected.getObjectNamePrefix(), value.getObjectNamePrefix()); - assertEquals(expected.getPayloadFormat(), value.getPayloadFormat()); - assertEquals(expected.getTopic(), value.getTopic()); - } -} diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java index 87f1a37b7..abfa97b98 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java @@ -16,24 +16,14 @@ package com.google.cloud.storage; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.createStrictMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; import static org.junit.Assert.assertEquals; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.util.List; import java.util.Map; -import org.junit.After; -import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -@RunWith(JUnit4.class) public class NotificationTest { private static final String ETAG = "0xFF00"; @@ -42,12 +32,12 @@ public class NotificationTest { private static final List EVENT_TYPES = ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); private static final String OBJECT_NAME_PREFIX = "index.html"; - private static final NotificationInfo.PayloadFormat PAYLOAD_FORMAT = - NotificationInfo.PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final Notification.PayloadFormat PAYLOAD_FORMAT = + Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; private static final String TOPIC = "projects/myProject/topics/topic1"; private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); - private static final NotificationInfo FULL_NOTIFICATION_INFO = - NotificationInfo.newBuilder(TOPIC) + private static final Notification NOTIFICATION = + Notification.newBuilder(TOPIC) .setEtag(ETAG) .setCustomAttributes(CUSTOM_ATTRIBUTES) .setSelfLink(SELF_LINK) @@ -56,74 +46,60 @@ public class NotificationTest { .setPayloadFormat(PAYLOAD_FORMAT) .setGeneratedId(GENERATED_ID) .build(); - private static final NotificationInfo NOTIFICATION_INFO = - NotificationInfo.newBuilder(TOPIC).build(); - private Storage storage; - private StorageOptions mockOptions = createMock(StorageOptions.class); - - @Before - public void setUp() { - storage = createStrictMock(Storage.class); + @Test + public void testToBuilder() { + compareBucketsNotification(NOTIFICATION, NOTIFICATION.toBuilder().build()); + Notification notification = NOTIFICATION.toBuilder().setGeneratedId("id").build(); + assertEquals("id", notification.getGeneratedId()); + notification = notification.toBuilder().setGeneratedId(GENERATED_ID).build(); + compareBucketsNotification(NOTIFICATION, notification); } - @After - public void tearDown() { - verify(storage); + @Test + public void testToBuilderIncomplete() { + Notification incompleteNotification = Notification.newBuilder(TOPIC).build(); + compareBucketsNotification(incompleteNotification, incompleteNotification.toBuilder().build()); } @Test - public void testBuilder() { - expect(storage.getOptions()).andReturn(mockOptions).times(2); - replay(storage); - Notification.Builder builder = - new Notification.Builder( - new Notification(storage, new NotificationInfo.BuilderImpl(NOTIFICATION_INFO))); - Notification notification = - builder - .setEtag(ETAG) - .setCustomAttributes(CUSTOM_ATTRIBUTES) - .setSelfLink(SELF_LINK) - .setEventTypes(EVENT_TYPES) - .setObjectNamePrefix(OBJECT_NAME_PREFIX) - .setPayloadFormat(PAYLOAD_FORMAT) - .setGeneratedId(GENERATED_ID) - .build(); - assertEquals(ETAG, notification.getEtag()); - assertEquals(GENERATED_ID, notification.getGeneratedId()); - assertEquals(SELF_LINK, notification.getSelfLink()); - assertEquals(EVENT_TYPES, notification.getEventTypes()); - assertEquals(OBJECT_NAME_PREFIX, notification.getObjectNamePrefix()); - assertEquals(PAYLOAD_FORMAT, notification.getPayloadFormat()); + public void testOf() { + Notification notification = Notification.of(TOPIC); assertEquals(TOPIC, notification.getTopic()); - assertEquals(CUSTOM_ATTRIBUTES, notification.getCustomAttributes()); } @Test - public void testToBuilder() { - expect(storage.getOptions()).andReturn(mockOptions).times(2); - replay(storage); - Notification notification = - new Notification(storage, new NotificationInfo.BuilderImpl(FULL_NOTIFICATION_INFO)); - compareBuckets(notification, notification.toBuilder().build()); + public void testBuilder() { + assertEquals(ETAG, NOTIFICATION.getEtag()); + assertEquals(GENERATED_ID, NOTIFICATION.getGeneratedId()); + assertEquals(SELF_LINK, NOTIFICATION.getSelfLink()); + assertEquals(EVENT_TYPES, NOTIFICATION.getEventTypes()); + assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION.getObjectNamePrefix()); + assertEquals(PAYLOAD_FORMAT, NOTIFICATION.getPayloadFormat()); + assertEquals(TOPIC, NOTIFICATION.getTopic()); + assertEquals(CUSTOM_ATTRIBUTES, NOTIFICATION.getCustomAttributes()); } @Test - public void testFromPb() { - expect(storage.getOptions()).andReturn(mockOptions).times(1); - replay(storage); - compareBuckets( - FULL_NOTIFICATION_INFO, Notification.fromPb(storage, FULL_NOTIFICATION_INFO.toPb())); + public void testToPbAndFromPb() { + compareBucketsNotification(NOTIFICATION, Notification.fromPb(NOTIFICATION.toPb())); + Notification notification = + Notification.of(TOPIC) + .toBuilder() + .setPayloadFormat(Notification.PayloadFormat.NONE) + .build(); + compareBucketsNotification(notification, Notification.fromPb(notification.toPb())); } - private void compareBuckets(NotificationInfo expected, NotificationInfo value) { - assertEquals(expected.getGeneratedId(), value.getGeneratedId()); - assertEquals(expected.getCustomAttributes(), value.getCustomAttributes()); - assertEquals(expected.getEtag(), value.getEtag()); - assertEquals(expected.getSelfLink(), value.getSelfLink()); - assertEquals(expected.getEventTypes(), value.getEventTypes()); - assertEquals(expected.getObjectNamePrefix(), value.getObjectNamePrefix()); - assertEquals(expected.getPayloadFormat(), value.getPayloadFormat()); - assertEquals(expected.getTopic().trim(), value.getTopic().trim()); + private void compareBucketsNotification(Notification expected, Notification actual) { + assertEquals(expected, actual); + assertEquals(expected.getGeneratedId(), actual.getGeneratedId()); + assertEquals(expected.getCustomAttributes(), actual.getCustomAttributes()); + assertEquals(expected.getEtag(), actual.getEtag()); + assertEquals(expected.getSelfLink(), actual.getSelfLink()); + assertEquals(expected.getEventTypes(), actual.getEventTypes()); + assertEquals(expected.getObjectNamePrefix(), actual.getObjectNamePrefix()); + assertEquals(expected.getPayloadFormat(), actual.getPayloadFormat()); + assertEquals(expected.getTopic(), actual.getTopic()); } } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java index 7ff8372fb..d038e832d 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java @@ -374,12 +374,12 @@ public long millisTime() { private static final List EVENT_TYPES = ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); private static final String OBJECT_NAME_PREFIX = "index.html"; - private static final NotificationInfo.PayloadFormat PAYLOAD_FORMAT = - NotificationInfo.PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final Notification.PayloadFormat PAYLOAD_FORMAT = + Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; private static final String TOPIC = "projects/myProject/topics/topic1"; private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); - private static final NotificationInfo NOTIFICATION_INFO_01 = - NotificationInfo.newBuilder(TOPIC) + private static final Notification NOTIFICATION_01 = + Notification.newBuilder(TOPIC) .setEtag(ETAG) .setCustomAttributes(CUSTOM_ATTRIBUTES) .setSelfLink(SELF_LINK) @@ -388,8 +388,8 @@ public long millisTime() { .setPayloadFormat(PAYLOAD_FORMAT) .setGeneratedId(GENERATED_ID) .build(); - private static final NotificationInfo NOTIFICATION_INFO_02 = - NotificationInfo.newBuilder(TOPIC) + private static final Notification NOTIFICATION_02 = + Notification.newBuilder(TOPIC) .setEtag(ETAG) .setCustomAttributes(CUSTOM_ATTRIBUTES) .setSelfLink(SELF_LINK) @@ -1679,17 +1679,17 @@ public void testWriterFailure() { @Test public void testCreateNotification() { - doReturn(NOTIFICATION_INFO_01.toPb()) + doReturn(NOTIFICATION_01.toPb()) .when(storageRpcMock) - .createNotification(BUCKET_NAME1, NOTIFICATION_INFO_01.toPb()); + .createNotification(BUCKET_NAME1, NOTIFICATION_01.toPb()); initializeService(); - Notification notification = storage.createNotification(BUCKET_NAME1, NOTIFICATION_INFO_01); + Notification notification = storage.createNotification(BUCKET_NAME1, NOTIFICATION_01); compareBucketsNotification(notification); } @Test public void testGetNotification() { - doReturn(NOTIFICATION_INFO_01.toPb()) + doReturn(NOTIFICATION_01.toPb()) .when(storageRpcMock) .getNotification(BUCKET_NAME1, GENERATED_ID); initializeService(); @@ -1699,7 +1699,7 @@ public void testGetNotification() { @Test public void testListNotification() { - doReturn(Arrays.asList(NOTIFICATION_INFO_01.toPb(), NOTIFICATION_INFO_02.toPb())) + doReturn(Arrays.asList(NOTIFICATION_01.toPb(), NOTIFICATION_02.toPb())) .when(storageRpcMock) .listNotifications(BUCKET_NAME1); initializeService(); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index af8e47d3e..538752a6a 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -74,7 +74,6 @@ import com.google.cloud.storage.HmacKey.HmacKeyState; import com.google.cloud.storage.HttpMethod; import com.google.cloud.storage.Notification; -import com.google.cloud.storage.NotificationInfo; import com.google.cloud.storage.PostPolicyV4; import com.google.cloud.storage.PostPolicyV4.PostFieldsV4; import com.google.cloud.storage.Rpo; @@ -231,8 +230,8 @@ public class ITStorageTest { private static final String ID = UUID.randomUUID().toString().substring(0, 8); private static final String TOPIC = String.format("projects/%s/topics/test_topic_foo_%s", PROJECT, ID); - private static final NotificationInfo.PayloadFormat PAYLOAD_FORMAT = - NotificationInfo.PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final Notification.PayloadFormat PAYLOAD_FORMAT = + Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); @BeforeClass @@ -454,12 +453,12 @@ private static Notification createNotification(TopicAdminClient topicAdminClient topicAdminClient.setIamPolicy(setIamPolicyRequest); // Create a notification on a bucket. - NotificationInfo notificationInfo = - NotificationInfo.newBuilder(TOPIC) + Notification bucketNotification = + Notification.newBuilder(TOPIC) .setCustomAttributes(CUSTOM_ATTRIBUTES) .setPayloadFormat(PAYLOAD_FORMAT) .build(); - notification = storage.createNotification(BUCKET, notificationInfo); + notification = storage.createNotification(BUCKET, bucketNotification); return notification; } From 9d0e8c4bf318f0628da0aaea91e129be05e1ccf2 Mon Sep 17 00:00:00 2001 From: athakor Date: Mon, 6 Jul 2020 14:38:22 +0530 Subject: [PATCH 04/18] feat: fix review changes --- .../google/cloud/storage/Notification.java | 19 +++++++++---------- .../com/google/cloud/storage/Storage.java | 8 ++++---- .../com/google/cloud/storage/StorageImpl.java | 8 ++++---- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java index 78a5dcc79..dd64a18b5 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -70,7 +70,7 @@ public com.google.api.services.storage.model.Notification apply( private final String etag; private final String selfLink; - /** Builder for {@code NotificatioInfo}. */ + /** Builder for {@code Notification}. */ public static class Builder { private String generatedId; @@ -107,7 +107,7 @@ public Builder setSelfLink(String selfLink) { return this; } - /** The name of the topic. It must have the format "projects/{project}/topics/{topic}". */ + /** Sets a topic in the format of "projects/{project}/topics/{topic}". */ public Builder setTopic(String topic) { this.topic = topic; return this; @@ -141,6 +141,7 @@ public Builder setCustomAttributes(Map customAttributes) { public Notification build() { checkNotNull(topic); + PATH_TEMPLATE.validatedMatch(topic, "topic must be in valid format"); return new Notification(this); } } @@ -256,13 +257,12 @@ com.google.api.services.storage.model.Notification toPb() { } /** - * Creates a {@code Notification} object for the provided topic name. + * Creates a {@code Notification} object for the provided topic. * - * @param topic The name of the topic. It must have the format - * "projects/{project}/topics/{topic}". + * @param topic a string in the format "projects/{project}/topics/{topic}" */ public static Notification of(String topic) { - PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); + PATH_TEMPLATE.validatedMatch(topic, "topic must be in valid format"); return newBuilder(topic).build(); } @@ -272,13 +272,12 @@ public Builder toBuilder() { } /** - * Returns a {@code Notification} builder where the topic's name is set to the provided name. + * Returns a {@code Notification.Builder} with the topic set. * - * @param topic The name of the topic. It must have the format - * "projects/{project}/topics/{topic}". + * @param topic a string in the format "projects/{project}/topics/{topic}" */ public static Builder newBuilder(String topic) { - PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); + PATH_TEMPLATE.validatedMatch(topic, "topic must be in valid format"); return new Builder(topic); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 34761ef90..eed408b82 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3640,11 +3640,11 @@ List testIamPermissions( * Gets the notification with the specified name on the bucket. * * @param bucket name of the bucket - * @param notification notification ID + * @param notificationId notification ID * @return the notification object that exist on the bucket or {@code null} if not found * @throws StorageException upon failure */ - Notification getNotification(String bucket, String notification); + Notification getNotification(String bucket, String notificationId); /** * Retrieves a list of notification subscriptions for a given bucket. @@ -3659,9 +3659,9 @@ List testIamPermissions( * Deletes the notification subscription with the specified name on the bucket. * * @param bucket name of the bucket - * @param notification ID of the notification to delete + * @param notificationId ID of the notification to delete * @return {@code true} if the notification has been deleted, {@code false} if not found * @throws StorageException upon failure */ - boolean deleteNotification(String bucket, String notification); + boolean deleteNotification(String bucket, String notificationId); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index 1cbf2957d..f48ca0d53 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -1395,14 +1395,14 @@ public com.google.api.services.storage.model.Notification call() { } @Override - public Notification getNotification(final String bucket, final String notification) { + public Notification getNotification(final String bucket, final String notificationId) { try { com.google.api.services.storage.model.Notification answer = runWithRetries( new Callable() { @Override public com.google.api.services.storage.model.Notification call() { - return storageRpc.getNotification(bucket, notification); + return storageRpc.getNotification(bucket, notificationId); } }, getOptions().getRetrySettings(), @@ -1435,13 +1435,13 @@ public List call() { } @Override - public boolean deleteNotification(final String bucket, final String notification) { + public boolean deleteNotification(final String bucket, final String notificationId) { try { return runWithRetries( new Callable() { @Override public Boolean call() { - return storageRpc.deleteNotification(bucket, notification); + return storageRpc.deleteNotification(bucket, notificationId); } }, getOptions().getRetrySettings(), From cd3776f0ee9227e29a48d776fcb4681b3565b3aa Mon Sep 17 00:00:00 2001 From: athakor Date: Mon, 13 Jul 2020 15:52:44 +0530 Subject: [PATCH 05/18] feat: addressed review changes --- .../google/cloud/storage/Notification.java | 20 +++++++--- .../com/google/cloud/storage/Storage.java | 40 +++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java index dd64a18b5..9536d1eaa 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -28,10 +28,14 @@ import java.util.Objects; /** - * Google Storage Notification metadata; + * A {@code Notification} object sends the information about the changes of objects in your buckets, + * where the information is added to the topic of your choice in the form of messages. For example, + * you can track objects that are created and deleted in your bucket. Each notification contains + * information describing both the event that triggered it and the object that changed. * - * @see Concepts and - * Terminology + *

You can send notifications to any topic in any project for which you have sufficient + * permissions. Once received by the topic, the resulting message can be sent to any number of + * subscribers to the topic. */ public class Notification implements Serializable { @@ -141,7 +145,7 @@ public Builder setCustomAttributes(Map customAttributes) { public Notification build() { checkNotNull(topic); - PATH_TEMPLATE.validatedMatch(topic, "topic must be in valid format"); + checkTopicFormat(topic); return new Notification(this); } } @@ -262,7 +266,7 @@ com.google.api.services.storage.model.Notification toPb() { * @param topic a string in the format "projects/{project}/topics/{topic}" */ public static Notification of(String topic) { - PATH_TEMPLATE.validatedMatch(topic, "topic must be in valid format"); + checkTopicFormat(topic); return newBuilder(topic).build(); } @@ -277,7 +281,7 @@ public Builder toBuilder() { * @param topic a string in the format "projects/{project}/topics/{topic}" */ public static Builder newBuilder(String topic) { - PATH_TEMPLATE.validatedMatch(topic, "topic must be in valid format"); + checkTopicFormat(topic); return new Builder(topic); } @@ -309,4 +313,8 @@ static Notification fromPb(com.google.api.services.storage.model.Notification no } return builder.build(); } + + private static void checkTopicFormat(String topic) { + PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); + } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index eed408b82..039529577 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3629,6 +3629,18 @@ List testIamPermissions( /** * Creates a notification subscription for a given bucket. * + *

Example of creating a notification subscription: + * + *

{@code
+   * String bucketName = "my-unique-bucket";
+   * String topic = "projects/myProject/topics/topic"
+   * Notification bucketNotification = Notification.newBuilder(topic)
+   *  .setCustomAttributes(ImmutableMap.of("label1", "value1"))
+   *  .setPayloadFormat(Notification.PayloadFormat.JSON_API_V1.JSON_API_V1)
+   *  .build();
+   * Notification notification = storage.createNotification(bucketName, bucketNotification);
+   * }
+ * * @param bucket name of the bucket * @param notification a {@code Notification} object * @return the notification that was created @@ -3639,6 +3651,14 @@ List testIamPermissions( /** * Gets the notification with the specified name on the bucket. * + *

Example of getting the notification: + * + *

{@code
+   * String bucketName = "my-unique-bucket";
+   * String notificationId = "my-unique-notification-id";
+   * Notification notification = storage.getNotification(bucketName, notificationId);
+   * }
+ * * @param bucket name of the bucket * @param notificationId notification ID * @return the notification object that exist on the bucket or {@code null} if not found @@ -3649,6 +3669,13 @@ List testIamPermissions( /** * Retrieves a list of notification subscriptions for a given bucket. * + *

Example of getting a service account. + * + *

{@code
+   * String bucketName = "my-unique-bucket";
+   * List notifications = storage.listNotifications(bucketName);
+   * }
+ * * @param bucket name of the bucket * @return a list of {@link Notification} objects that exist on the bucket. * @throws StorageException upon failure @@ -3658,6 +3685,19 @@ List testIamPermissions( /** * Deletes the notification subscription with the specified name on the bucket. * + *

Example of getting a service account. + * + *

{@code
+   * String bucketName = "my-unique-bucket";
+   * String notificationId = "my-unique-notification-id";
+   * boolean deleted = storage.deleteNotification(bucketName, notificationId);
+   * if (deleted) {
+   *   // the notification was deleted
+   * } else {
+   *   // the notification was not found
+   * }
+   * }
+ * * @param bucket name of the bucket * @param notificationId ID of the notification to delete * @return {@code true} if the notification has been deleted, {@code false} if not found From ec7c50ca00f62312f2d2f129ef05502cbddb67b7 Mon Sep 17 00:00:00 2001 From: athakor Date: Mon, 13 Jul 2020 16:03:53 +0530 Subject: [PATCH 06/18] feat: change javaDoc --- .../src/main/java/com/google/cloud/storage/Storage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 039529577..781e00460 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3669,7 +3669,7 @@ List testIamPermissions( /** * Retrieves a list of notification subscriptions for a given bucket. * - *

Example of getting a service account. + *

Example of listing the bucket notifications: * *

{@code
    * String bucketName = "my-unique-bucket";
@@ -3685,7 +3685,7 @@ List testIamPermissions(
   /**
    * Deletes the notification subscription with the specified name on the bucket.
    *
-   * 

Example of getting a service account. + *

Example of deleting the notification: * *

{@code
    * String bucketName = "my-unique-bucket";

From 500e025bdda48a55e9a2d2c15dd7acd3b98fda6c Mon Sep 17 00:00:00 2001
From: athakor 
Date: Tue, 14 Jul 2020 14:37:45 +0530
Subject: [PATCH 07/18] feat: addressed review changes

---
 .../java/com/google/cloud/storage/Notification.java | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java
index 9536d1eaa..e46ca4501 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java
@@ -28,14 +28,11 @@
 import java.util.Objects;
 
 /**
- * A {@code Notification} object sends the information about the changes of objects in your buckets,
- * where the information is added to the topic of your choice in the form of messages. For example,
- * you can track objects that are created and deleted in your bucket. Each notification contains
- * information describing both the event that triggered it and the object that changed.
+ * The class representing Pub/Sub notifications for the Storage.
  *
- * 

You can send notifications to any topic in any project for which you have sufficient - * permissions. Once received by the topic, the resulting message can be sent to any number of - * subscribers to the topic. + * @see pubsub-notifications + * for details. */ public class Notification implements Serializable { @@ -101,7 +98,7 @@ private Builder(Notification notification) { objectNamePrefix = notification.objectNamePrefix; } - public Builder setGeneratedId(String generatedId) { + Builder setGeneratedId(String generatedId) { this.generatedId = generatedId; return this; } From 0dbf97949d482f1ae7a4fcab5cb4171878503fe8 Mon Sep 17 00:00:00 2001 From: athakor Date: Tue, 14 Jul 2020 21:36:44 +0530 Subject: [PATCH 08/18] feat: fix review changes --- .../clirr-ignored-differences.xml | 2 +- .../google/cloud/storage/Notification.java | 34 ++++++++++++++----- .../com/google/cloud/storage/Storage.java | 19 ++++++----- .../com/google/cloud/storage/StorageImpl.java | 2 +- .../cloud/storage/NotificationTest.java | 12 +++---- .../cloud/storage/StorageImplMockitoTest.java | 13 +++---- .../cloud/storage/it/ITStorageTest.java | 10 +++--- 7 files changed, 55 insertions(+), 37 deletions(-) diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml index 04d2052ad..73a70b8f0 100644 --- a/google-cloud-storage/clirr-ignored-differences.xml +++ b/google-cloud-storage/clirr-ignored-differences.xml @@ -13,7 +13,7 @@ com/google/cloud/storage/Storage - com.google.cloud.storage.Notification createNotification(java.lang.String, com.google.cloud.storage.Notification) + com.google.cloud.storage.Notification addNotification(java.lang.String, com.google.cloud.storage.Notification) 7012 diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java index e46ca4501..ee77f87a7 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -20,9 +20,9 @@ import com.google.api.pathtemplate.PathTemplate; import com.google.common.base.Function; import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.io.Serializable; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -45,6 +45,13 @@ public enum PayloadFormat { NONE } + public enum EventType { + OBJECT_FINALIZE, + OBJECT_METADATA_UPDATE, + OBJECT_DELETE, + OBJECT_ARCHIVE + } + static final Function FROM_PB_FUNCTION = new Function() { @@ -64,7 +71,7 @@ public com.google.api.services.storage.model.Notification apply( }; private final String generatedId; private final String topic; - private final List eventTypes; + private final EventType[] eventTypes; private final Map customAttributes; private final PayloadFormat payloadFormat; private final String objectNamePrefix; @@ -76,7 +83,7 @@ public static class Builder { private String generatedId; private String topic; - private List eventTypes; + private EventType[] eventTypes; private Map customAttributes; private PayloadFormat payloadFormat; private String objectNamePrefix; @@ -124,8 +131,8 @@ public Builder setObjectNamePrefix(String objectNamePrefix) { return this; } - public Builder setEventTypes(Iterable eventTypes) { - this.eventTypes = eventTypes != null ? ImmutableList.copyOf(eventTypes) : null; + public Builder setEventTypes(EventType... eventTypes) { + this.eventTypes = eventTypes != null && eventTypes.length > 0 ? eventTypes : null; return this; } @@ -199,7 +206,7 @@ public String getEtag() { * @see Cross-Origin Resource Sharing * (CORS) */ - public List getEventTypes() { + public EventType[] getEventTypes() { return eventTypes; } @@ -240,8 +247,12 @@ com.google.api.services.storage.model.Notification toPb() { if (customAttributes != null) { notificationPb.setCustomAttributes(customAttributes); } - if (eventTypes != null) { - notificationPb.setEventTypes(eventTypes); + if (eventTypes != null && eventTypes.length > 0) { + List eventTypesPb = new ArrayList<>(); + for (EventType eventType : eventTypes) { + eventTypesPb.add(eventType.toString()); + } + notificationPb.setEventTypes(eventTypesPb); } if (objectNamePrefix != null) { notificationPb.setObjectNamePrefix(objectNamePrefix); @@ -303,7 +314,12 @@ static Notification fromPb(com.google.api.services.storage.model.Notification no builder.setTopic(notificationPb.getTopic()); } if (notificationPb.getEventTypes() != null) { - builder.setEventTypes(notificationPb.getEventTypes()); + List eventTypesPb = notificationPb.getEventTypes(); + EventType[] eventTypes = new EventType[eventTypesPb.size()]; + for (int index = 0; index < eventTypesPb.size(); index++) { + eventTypes[index] = EventType.valueOf(eventTypesPb.get(index)); + } + builder.setEventTypes(eventTypes); } if (notificationPb.getPayloadFormat() != null) { builder.setPayloadFormat(PayloadFormat.valueOf(notificationPb.getPayloadFormat())); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 781e00460..9cf060609 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3627,29 +3627,30 @@ List testIamPermissions( ServiceAccount getServiceAccount(String projectId); /** - * Creates a notification subscription for a given bucket. + * Adds a new notification to the bucket. * - *

Example of creating a notification subscription: + *

Example of adding a notification: * *

{@code
    * String bucketName = "my-unique-bucket";
-   * String topic = "projects/myProject/topics/topic"
+   * String topic = "projects/myProject/topics/myTopic"
    * Notification bucketNotification = Notification.newBuilder(topic)
    *  .setCustomAttributes(ImmutableMap.of("label1", "value1"))
+   *  .setEventTypes(Notification.EventType.OBJECT_FINALIZE)
    *  .setPayloadFormat(Notification.PayloadFormat.JSON_API_V1.JSON_API_V1)
    *  .build();
-   * Notification notification = storage.createNotification(bucketName, bucketNotification);
+   * Notification notification = storage.addNotification(bucketName, bucketNotification);
    * }
* * @param bucket name of the bucket * @param notification a {@code Notification} object - * @return the notification that was created + * @return the created notification * @throws StorageException upon failure */ - Notification createNotification(String bucket, Notification notification); + Notification addNotification(String bucket, Notification notification); /** - * Gets the notification with the specified name on the bucket. + * Gets the notification with the specified id. * *

Example of getting the notification: * @@ -3667,7 +3668,7 @@ List testIamPermissions( Notification getNotification(String bucket, String notificationId); /** - * Retrieves a list of notification subscriptions for a given bucket. + * Retrieves the list of notifications associated with the bucket. * *

Example of listing the bucket notifications: * @@ -3683,7 +3684,7 @@ List testIamPermissions( List listNotifications(String bucket); /** - * Deletes the notification subscription with the specified name on the bucket. + * Deletes the notification with the specified id. * *

Example of deleting the notification: * diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index f48ca0d53..929c7ba84 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -1375,7 +1375,7 @@ private U run(ResultRetryAlgorithm algorithm, Callable c, Function< } @Override - public Notification createNotification(final String bucket, final Notification notification) { + public Notification addNotification(final String bucket, final Notification notification) { final com.google.api.services.storage.model.Notification notificationPb = notification.toPb(); try { return Notification.fromPb( diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java index abfa97b98..c146368b0 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java @@ -16,11 +16,10 @@ package com.google.cloud.storage; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import java.util.List; import java.util.Map; import org.junit.Test; @@ -29,8 +28,9 @@ public class NotificationTest { private static final String ETAG = "0xFF00"; private static final String GENERATED_ID = "B/N:1"; private static final String SELF_LINK = "http://storage/b/n"; - private static final List EVENT_TYPES = - ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); + private static final Notification.EventType[] EVENT_TYPES = { + Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE + }; private static final String OBJECT_NAME_PREFIX = "index.html"; private static final Notification.PayloadFormat PAYLOAD_FORMAT = Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; @@ -73,7 +73,7 @@ public void testBuilder() { assertEquals(ETAG, NOTIFICATION.getEtag()); assertEquals(GENERATED_ID, NOTIFICATION.getGeneratedId()); assertEquals(SELF_LINK, NOTIFICATION.getSelfLink()); - assertEquals(EVENT_TYPES, NOTIFICATION.getEventTypes()); + assertArrayEquals(EVENT_TYPES, NOTIFICATION.getEventTypes()); assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION.getObjectNamePrefix()); assertEquals(PAYLOAD_FORMAT, NOTIFICATION.getPayloadFormat()); assertEquals(TOPIC, NOTIFICATION.getTopic()); @@ -97,7 +97,7 @@ private void compareBucketsNotification(Notification expected, Notification actu assertEquals(expected.getCustomAttributes(), actual.getCustomAttributes()); assertEquals(expected.getEtag(), actual.getEtag()); assertEquals(expected.getSelfLink(), actual.getSelfLink()); - assertEquals(expected.getEventTypes(), actual.getEventTypes()); + assertArrayEquals(expected.getEventTypes(), actual.getEventTypes()); assertEquals(expected.getObjectNamePrefix(), actual.getObjectNamePrefix()); assertEquals(expected.getPayloadFormat(), actual.getPayloadFormat()); assertEquals(expected.getTopic(), actual.getTopic()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java index d038e832d..cc77d533a 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java @@ -371,8 +371,9 @@ public long millisTime() { private static final String ETAG = "0xFF00"; private static final String GENERATED_ID = "B/N:1"; private static final String SELF_LINK = "http://storage/b/n"; - private static final List EVENT_TYPES = - ImmutableList.of("OBJECT_FINALIZE", "OBJECT_METADATA_UPDATE"); + private static final Notification.EventType[] EVENT_TYPES = { + Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE + }; private static final String OBJECT_NAME_PREFIX = "index.html"; private static final Notification.PayloadFormat PAYLOAD_FORMAT = Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; @@ -393,7 +394,7 @@ public long millisTime() { .setEtag(ETAG) .setCustomAttributes(CUSTOM_ATTRIBUTES) .setSelfLink(SELF_LINK) - .setEventTypes(EVENT_TYPES) + .setEventTypes(Notification.EventType.OBJECT_FINALIZE) .setObjectNamePrefix(OBJECT_NAME_PREFIX) .setPayloadFormat(PAYLOAD_FORMAT) .setGeneratedId(GENERATED_ID) @@ -1678,12 +1679,12 @@ public void testWriterFailure() { } @Test - public void testCreateNotification() { + public void testAddNotification() { doReturn(NOTIFICATION_01.toPb()) .when(storageRpcMock) .createNotification(BUCKET_NAME1, NOTIFICATION_01.toPb()); initializeService(); - Notification notification = storage.createNotification(BUCKET_NAME1, NOTIFICATION_01); + Notification notification = storage.addNotification(BUCKET_NAME1, NOTIFICATION_01); compareBucketsNotification(notification); } @@ -1720,7 +1721,7 @@ private void compareBucketsNotification(Notification value) { assertEquals(CUSTOM_ATTRIBUTES, value.getCustomAttributes()); assertEquals(ETAG, value.getEtag()); assertEquals(SELF_LINK, value.getSelfLink()); - assertEquals(EVENT_TYPES, value.getEventTypes()); + assertArrayEquals(EVENT_TYPES, value.getEventTypes()); assertEquals(OBJECT_NAME_PREFIX, value.getObjectNamePrefix()); assertEquals(PAYLOAD_FORMAT.name(), value.getPayloadFormat().name()); assertEquals(TOPIC, value.getTopic()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index 538752a6a..e29703998 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -254,9 +254,9 @@ public static void beforeClass() throws IOException { // Prepare KMS KeyRing for CMEK tests prepareKmsKeys(); - // Create notification. + // Add notification. topicAdminClient = TopicAdminClient.create(); - createNotification(topicAdminClient); + addNotification(topicAdminClient); } private static void unsetRequesterPays() { @@ -438,7 +438,7 @@ private static String ensureKmsKeyExistsForTests( return kmsKeyResourcePath; } - private static Notification createNotification(TopicAdminClient topicAdminClient) { + private static Notification addNotification(TopicAdminClient topicAdminClient) { topicAdminClient.createTopic(TOPIC); GetIamPolicyRequest getIamPolicyRequest = GetIamPolicyRequest.newBuilder().setResource(TOPIC).build(); @@ -452,13 +452,13 @@ private static Notification createNotification(TopicAdminClient topicAdminClient .build(); topicAdminClient.setIamPolicy(setIamPolicyRequest); - // Create a notification on a bucket. + // Add a new notification to the bucket. Notification bucketNotification = Notification.newBuilder(TOPIC) .setCustomAttributes(CUSTOM_ATTRIBUTES) .setPayloadFormat(PAYLOAD_FORMAT) .build(); - notification = storage.createNotification(BUCKET, bucketNotification); + notification = storage.addNotification(BUCKET, bucketNotification); return notification; } From 915dca41593aef9a3f24f446a52f1f2dae347057 Mon Sep 17 00:00:00 2001 From: athakor Date: Wed, 15 Jul 2020 12:33:44 +0530 Subject: [PATCH 09/18] feat: addressed few nits --- .../google/cloud/storage/Notification.java | 27 ++++++++++++------- .../com/google/cloud/storage/Storage.java | 4 +-- .../cloud/storage/NotificationTest.java | 13 ++++----- .../cloud/storage/StorageImplMockitoTest.java | 10 +++---- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java index ee77f87a7..7c8c84e78 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -20,6 +20,7 @@ import com.google.api.pathtemplate.PathTemplate; import com.google.common.base.Function; import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.io.Serializable; import java.util.ArrayList; @@ -71,7 +72,7 @@ public com.google.api.services.storage.model.Notification apply( }; private final String generatedId; private final String topic; - private final EventType[] eventTypes; + private final List eventTypes; private final Map customAttributes; private final PayloadFormat payloadFormat; private final String objectNamePrefix; @@ -83,7 +84,7 @@ public static class Builder { private String generatedId; private String topic; - private EventType[] eventTypes; + private List eventTypes; private Map customAttributes; private PayloadFormat payloadFormat; private String objectNamePrefix; @@ -131,8 +132,8 @@ public Builder setObjectNamePrefix(String objectNamePrefix) { return this; } - public Builder setEventTypes(EventType... eventTypes) { - this.eventTypes = eventTypes != null && eventTypes.length > 0 ? eventTypes : null; + public Builder setEventTypes(List eventTypes) { + this.eventTypes = eventTypes != null ? ImmutableList.copyOf(eventTypes) : null; return this; } @@ -206,7 +207,7 @@ public String getEtag() { * @see Cross-Origin Resource Sharing * (CORS) */ - public EventType[] getEventTypes() { + public List getEventTypes() { return eventTypes; } @@ -247,7 +248,7 @@ com.google.api.services.storage.model.Notification toPb() { if (customAttributes != null) { notificationPb.setCustomAttributes(customAttributes); } - if (eventTypes != null && eventTypes.length > 0) { + if (eventTypes != null && eventTypes.size() > 0) { List eventTypesPb = new ArrayList<>(); for (EventType eventType : eventTypes) { eventTypesPb.add(eventType.toString()); @@ -271,6 +272,13 @@ com.google.api.services.storage.model.Notification toPb() { /** * Creates a {@code Notification} object for the provided topic. * + *

Example of creating the notification object: + * + *

{@code
+   * String topic = "projects/myProject/topics/myTopic"
+   * Notification notification = Notification.of(topic)
+   * }
+ * * @param topic a string in the format "projects/{project}/topics/{topic}" */ public static Notification of(String topic) { @@ -314,10 +322,9 @@ static Notification fromPb(com.google.api.services.storage.model.Notification no builder.setTopic(notificationPb.getTopic()); } if (notificationPb.getEventTypes() != null) { - List eventTypesPb = notificationPb.getEventTypes(); - EventType[] eventTypes = new EventType[eventTypesPb.size()]; - for (int index = 0; index < eventTypesPb.size(); index++) { - eventTypes[index] = EventType.valueOf(eventTypesPb.get(index)); + List eventTypes = new ArrayList<>(); + for (String eventType : notificationPb.getEventTypes()) { + eventTypes.add(EventType.valueOf(eventType)); } builder.setEventTypes(eventTypes); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 9cf060609..a1f05295b 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3636,8 +3636,8 @@ List testIamPermissions( * String topic = "projects/myProject/topics/myTopic" * Notification bucketNotification = Notification.newBuilder(topic) * .setCustomAttributes(ImmutableMap.of("label1", "value1")) - * .setEventTypes(Notification.EventType.OBJECT_FINALIZE) - * .setPayloadFormat(Notification.PayloadFormat.JSON_API_V1.JSON_API_V1) + * .setEventTypes(ImmutableList.of(Notification.EventType.OBJECT_FINALIZE)) + * .setPayloadFormat(Notification.PayloadFormat.JSON_API_V1) * .build(); * Notification notification = storage.addNotification(bucketName, bucketNotification); * }
diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java index c146368b0..ecb2937d4 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java @@ -16,10 +16,11 @@ package com.google.cloud.storage; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import java.util.List; import java.util.Map; import org.junit.Test; @@ -28,9 +29,9 @@ public class NotificationTest { private static final String ETAG = "0xFF00"; private static final String GENERATED_ID = "B/N:1"; private static final String SELF_LINK = "http://storage/b/n"; - private static final Notification.EventType[] EVENT_TYPES = { - Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE - }; + private static final List EVENT_TYPES = + ImmutableList.of( + Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE); private static final String OBJECT_NAME_PREFIX = "index.html"; private static final Notification.PayloadFormat PAYLOAD_FORMAT = Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; @@ -73,7 +74,7 @@ public void testBuilder() { assertEquals(ETAG, NOTIFICATION.getEtag()); assertEquals(GENERATED_ID, NOTIFICATION.getGeneratedId()); assertEquals(SELF_LINK, NOTIFICATION.getSelfLink()); - assertArrayEquals(EVENT_TYPES, NOTIFICATION.getEventTypes()); + assertEquals(EVENT_TYPES, NOTIFICATION.getEventTypes()); assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION.getObjectNamePrefix()); assertEquals(PAYLOAD_FORMAT, NOTIFICATION.getPayloadFormat()); assertEquals(TOPIC, NOTIFICATION.getTopic()); @@ -97,7 +98,7 @@ private void compareBucketsNotification(Notification expected, Notification actu assertEquals(expected.getCustomAttributes(), actual.getCustomAttributes()); assertEquals(expected.getEtag(), actual.getEtag()); assertEquals(expected.getSelfLink(), actual.getSelfLink()); - assertArrayEquals(expected.getEventTypes(), actual.getEventTypes()); + assertEquals(expected.getEventTypes(), actual.getEventTypes()); assertEquals(expected.getObjectNamePrefix(), actual.getObjectNamePrefix()); assertEquals(expected.getPayloadFormat(), actual.getPayloadFormat()); assertEquals(expected.getTopic(), actual.getTopic()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java index cc77d533a..cb562d2cd 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java @@ -371,9 +371,9 @@ public long millisTime() { private static final String ETAG = "0xFF00"; private static final String GENERATED_ID = "B/N:1"; private static final String SELF_LINK = "http://storage/b/n"; - private static final Notification.EventType[] EVENT_TYPES = { - Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE - }; + private static final List EVENT_TYPES = + ImmutableList.of( + Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE); private static final String OBJECT_NAME_PREFIX = "index.html"; private static final Notification.PayloadFormat PAYLOAD_FORMAT = Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; @@ -394,7 +394,7 @@ public long millisTime() { .setEtag(ETAG) .setCustomAttributes(CUSTOM_ATTRIBUTES) .setSelfLink(SELF_LINK) - .setEventTypes(Notification.EventType.OBJECT_FINALIZE) + .setEventTypes(EVENT_TYPES) .setObjectNamePrefix(OBJECT_NAME_PREFIX) .setPayloadFormat(PAYLOAD_FORMAT) .setGeneratedId(GENERATED_ID) @@ -1721,7 +1721,7 @@ private void compareBucketsNotification(Notification value) { assertEquals(CUSTOM_ATTRIBUTES, value.getCustomAttributes()); assertEquals(ETAG, value.getEtag()); assertEquals(SELF_LINK, value.getSelfLink()); - assertArrayEquals(EVENT_TYPES, value.getEventTypes()); + assertEquals(EVENT_TYPES, value.getEventTypes()); assertEquals(OBJECT_NAME_PREFIX, value.getObjectNamePrefix()); assertEquals(PAYLOAD_FORMAT.name(), value.getPayloadFormat().name()); assertEquals(TOPIC, value.getTopic()); From 2897b6b7af488e7d46000fbd50e107d3dde77a14 Mon Sep 17 00:00:00 2001 From: athakor Date: Wed, 15 Jul 2020 13:47:14 +0530 Subject: [PATCH 10/18] feat: fix review changes --- .../java/com/google/cloud/storage/Notification.java | 13 +++++++------ .../main/java/com/google/cloud/storage/Storage.java | 2 +- .../com/google/cloud/storage/NotificationTest.java | 11 +++++------ .../cloud/storage/StorageImplMockitoTest.java | 8 ++++---- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java index 7c8c84e78..7c18354f6 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -20,10 +20,10 @@ import com.google.api.pathtemplate.PathTemplate; import com.google.common.base.Function; import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.io.Serializable; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; @@ -132,8 +132,8 @@ public Builder setObjectNamePrefix(String objectNamePrefix) { return this; } - public Builder setEventTypes(List eventTypes) { - this.eventTypes = eventTypes != null ? ImmutableList.copyOf(eventTypes) : null; + public Builder setEventTypes(EventType... eventTypes) { + this.eventTypes = eventTypes != null ? Arrays.asList(eventTypes) : null; return this; } @@ -322,9 +322,10 @@ static Notification fromPb(com.google.api.services.storage.model.Notification no builder.setTopic(notificationPb.getTopic()); } if (notificationPb.getEventTypes() != null) { - List eventTypes = new ArrayList<>(); - for (String eventType : notificationPb.getEventTypes()) { - eventTypes.add(EventType.valueOf(eventType)); + List eventTypesPb = notificationPb.getEventTypes(); + EventType[] eventTypes = new EventType[eventTypesPb.size()]; + for (int index = 0; index < eventTypesPb.size(); index++) { + eventTypes[index] = EventType.valueOf(eventTypesPb.get(index)); } builder.setEventTypes(eventTypes); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index a1f05295b..4001f67bb 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3636,7 +3636,7 @@ List testIamPermissions( * String topic = "projects/myProject/topics/myTopic" * Notification bucketNotification = Notification.newBuilder(topic) * .setCustomAttributes(ImmutableMap.of("label1", "value1")) - * .setEventTypes(ImmutableList.of(Notification.EventType.OBJECT_FINALIZE)) + * .setEventTypes(Notification.EventType.OBJECT_FINALIZE) * .setPayloadFormat(Notification.PayloadFormat.JSON_API_V1) * .build(); * Notification notification = storage.addNotification(bucketName, bucketNotification); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java index ecb2937d4..e6fc76418 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java @@ -18,9 +18,8 @@ import static org.junit.Assert.assertEquals; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import java.util.List; +import java.util.Arrays; import java.util.Map; import org.junit.Test; @@ -29,9 +28,9 @@ public class NotificationTest { private static final String ETAG = "0xFF00"; private static final String GENERATED_ID = "B/N:1"; private static final String SELF_LINK = "http://storage/b/n"; - private static final List EVENT_TYPES = - ImmutableList.of( - Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE); + private static final Notification.EventType[] EVENT_TYPES = { + Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE + }; private static final String OBJECT_NAME_PREFIX = "index.html"; private static final Notification.PayloadFormat PAYLOAD_FORMAT = Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; @@ -74,11 +73,11 @@ public void testBuilder() { assertEquals(ETAG, NOTIFICATION.getEtag()); assertEquals(GENERATED_ID, NOTIFICATION.getGeneratedId()); assertEquals(SELF_LINK, NOTIFICATION.getSelfLink()); - assertEquals(EVENT_TYPES, NOTIFICATION.getEventTypes()); assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION.getObjectNamePrefix()); assertEquals(PAYLOAD_FORMAT, NOTIFICATION.getPayloadFormat()); assertEquals(TOPIC, NOTIFICATION.getTopic()); assertEquals(CUSTOM_ATTRIBUTES, NOTIFICATION.getCustomAttributes()); + assertEquals(Arrays.asList(EVENT_TYPES), NOTIFICATION.getEventTypes()); } @Test diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java index cb562d2cd..8dca7ee5b 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java @@ -371,9 +371,9 @@ public long millisTime() { private static final String ETAG = "0xFF00"; private static final String GENERATED_ID = "B/N:1"; private static final String SELF_LINK = "http://storage/b/n"; - private static final List EVENT_TYPES = - ImmutableList.of( - Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE); + private static final Notification.EventType[] EVENT_TYPES = { + Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE + }; private static final String OBJECT_NAME_PREFIX = "index.html"; private static final Notification.PayloadFormat PAYLOAD_FORMAT = Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; @@ -1721,9 +1721,9 @@ private void compareBucketsNotification(Notification value) { assertEquals(CUSTOM_ATTRIBUTES, value.getCustomAttributes()); assertEquals(ETAG, value.getEtag()); assertEquals(SELF_LINK, value.getSelfLink()); - assertEquals(EVENT_TYPES, value.getEventTypes()); assertEquals(OBJECT_NAME_PREFIX, value.getObjectNamePrefix()); assertEquals(PAYLOAD_FORMAT.name(), value.getPayloadFormat().name()); assertEquals(TOPIC, value.getTopic()); + assertEquals(Arrays.asList(EVENT_TYPES), value.getEventTypes()); } } From 45ae9d9f1d5afb7a27e46740eb0d20fde37389b4 Mon Sep 17 00:00:00 2001 From: athakor Date: Thu, 16 Jul 2020 00:01:00 +0530 Subject: [PATCH 11/18] feat: fix minor changes and change the tests to provide better coverage --- .../google/cloud/storage/Notification.java | 34 ++---- .../com/google/cloud/storage/Storage.java | 4 +- .../com/google/cloud/storage/StorageImpl.java | 4 +- .../cloud/storage/spi/v1/HttpStorageRpc.java | 6 +- .../cloud/storage/spi/v1/StorageRpc.java | 16 +-- .../storage/testing/StorageRpcTestBase.java | 4 +- .../cloud/storage/NotificationTest.java | 18 ++- .../cloud/storage/StorageImplMockitoTest.java | 4 +- .../cloud/storage/it/ITStorageTest.java | 113 +++++++++--------- 9 files changed, 102 insertions(+), 101 deletions(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java index 7c18354f6..f1bf9ded1 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -29,11 +29,9 @@ import java.util.Objects; /** - * The class representing Pub/Sub notifications for the Storage. - * - * @see pubsub-notifications - * for details. + * The class representing Pub/Sub notifications for the Storage. See pubsub-notifications for + * details. */ public class Notification implements Serializable { @@ -106,7 +104,7 @@ private Builder(Notification notification) { objectNamePrefix = notification.objectNamePrefix; } - Builder setGeneratedId(String generatedId) { + private Builder setGeneratedId(String generatedId) { this.generatedId = generatedId; return this; } @@ -171,7 +169,7 @@ public String getGeneratedId() { return generatedId; } - /** Returns the topic to which this subscription publishes. */ + /** Returns the topic in Pub/Sub that receives notifications. */ public String getTopic() { return topic; } @@ -192,20 +190,18 @@ public String getObjectNamePrefix() { } /** - * Returns HTTP 1.1 Entity tag for the notification. - * - * @see Entity Tags + * Returns HTTP 1.1 Entity tag for the notification. See Entity Tags */ public String getEtag() { return etag; } /** - * Returns the list of event types that this notification will apply to. If empty, notifications - * will be sent on all event types. - * - * @see Cross-Origin Resource Sharing - * (CORS) + * Returns the events that trigger a notification to be sent. If empty, notifications are + * triggered by any event. See Event types to get + * list of available events. */ public List getEventTypes() { return eventTypes; @@ -214,9 +210,6 @@ public List getEventTypes() { /** * Returns the list of additional attributes to attach to each Cloud PubSub message published for * this notification subscription. - * - * @see - * About Access Control Lists */ public Map getCustomAttributes() { return customAttributes; @@ -224,7 +217,7 @@ public Map getCustomAttributes() { @Override public int hashCode() { - return Objects.hash(getTopic()); + return toPb().hashCode(); } @Override @@ -318,9 +311,6 @@ static Notification fromPb(com.google.api.services.storage.model.Notification no if (notificationPb.getObjectNamePrefix() != null) { builder.setObjectNamePrefix(notificationPb.getObjectNamePrefix()); } - if (notificationPb.getTopic() != null) { - builder.setTopic(notificationPb.getTopic()); - } if (notificationPb.getEventTypes() != null) { List eventTypesPb = notificationPb.getEventTypes(); EventType[] eventTypes = new EventType[eventTypesPb.size()]; diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 4001f67bb..bb97c66c0 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3662,7 +3662,7 @@ List testIamPermissions( * * @param bucket name of the bucket * @param notificationId notification ID - * @return the notification object that exist on the bucket or {@code null} if not found + * @return the {@code Notification} object with the given id or {@code null} if not found * @throws StorageException upon failure */ Notification getNotification(String bucket, String notificationId); @@ -3678,7 +3678,7 @@ List testIamPermissions( * }
* * @param bucket name of the bucket - * @return a list of {@link Notification} objects that exist on the bucket. + * @return a list of {@link Notification} objects added to the bucket. * @throws StorageException upon failure */ List listNotifications(String bucket); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index 929c7ba84..503347d4e 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -1428,7 +1428,9 @@ public List call() { getOptions().getRetrySettings(), EXCEPTION_HANDLER, getOptions().getClock()); - return Lists.transform(answer, Notification.FROM_PB_FUNCTION); + return answer == null + ? ImmutableList.of() + : Lists.transform(answer, Notification.FROM_PB_FUNCTION); } catch (RetryHelperException e) { throw StorageException.translateAndThrow(e); } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java index 6a905199d..d0c1ff8a9 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java @@ -1610,7 +1610,11 @@ public Notification getNotification(String bucket, String notification) { return storage.notifications().get(bucket, notification).execute(); } catch (IOException ex) { span.setStatus(Status.UNKNOWN.withDescription(ex.getMessage())); - throw translate(ex); + StorageException serviceException = translate(ex); + if (serviceException.getCode() == HTTP_NOT_FOUND) { + return null; + } + throw serviceException; } finally { scope.close(); span.end(); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java index 932c11581..c600723bd 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/StorageRpc.java @@ -561,15 +561,15 @@ TestIamPermissionsResponse testIamPermissions( String bucket, List permissions, Map options); /** - * Deletes the notification subscription with the specified name on the bucket. + * Deletes the notification with the specified id on the bucket. * * @return {@code true} if the notification has been deleted, {@code false} if not found * @throws StorageException upon failure */ - boolean deleteNotification(String bucket, String notification); + boolean deleteNotification(String bucket, String id); /** - * Retrieves a list of notification subscriptions for a given bucket. + * Retrieves the list of notifications associated with the bucket. * * @return a list of {@link Notification} objects that exist on the bucket. * @throws StorageException upon failure @@ -577,20 +577,20 @@ TestIamPermissionsResponse testIamPermissions( List listNotifications(String bucket); /** - * Creates a notification subscription for a given bucket. + * Creates the notification for a given bucket. * - * @return the notification that was created. + * @return the created notification. * @throws StorageException upon failure */ Notification createNotification(String bucket, Notification notification); /** - * Gets the notification with the specified name on the bucket. + * Gets the notification with the specified id. * - * @return the notification object that exist on the bucket. + * @return the {@code Notification} object with the given id or {@code null} if not found * @throws StorageException upon failure */ - Notification getNotification(String bucket, String notification); + Notification getNotification(String bucket, String id); /** * Lock retention policy for the provided bucket. diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java index f420ed1e6..81e7eee58 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/testing/StorageRpcTestBase.java @@ -287,7 +287,7 @@ public TestIamPermissionsResponse testIamPermissions( } @Override - public boolean deleteNotification(String bucket, String notification) { + public boolean deleteNotification(String bucket, String id) { throw new UnsupportedOperationException("Not implemented yet"); } @@ -302,7 +302,7 @@ public Notification createNotification(String bucket, Notification notification) } @Override - public Notification getNotification(String bucket, String notification) { + public Notification getNotification(String bucket, String id) { throw new UnsupportedOperationException("Not implemented yet"); } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java index e6fc76418..580ec7f82 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java @@ -17,6 +17,7 @@ package com.google.cloud.storage; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import com.google.common.collect.ImmutableMap; import java.util.Arrays; @@ -26,7 +27,6 @@ public class NotificationTest { private static final String ETAG = "0xFF00"; - private static final String GENERATED_ID = "B/N:1"; private static final String SELF_LINK = "http://storage/b/n"; private static final Notification.EventType[] EVENT_TYPES = { Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE @@ -44,15 +44,14 @@ public class NotificationTest { .setEventTypes(EVENT_TYPES) .setObjectNamePrefix(OBJECT_NAME_PREFIX) .setPayloadFormat(PAYLOAD_FORMAT) - .setGeneratedId(GENERATED_ID) .build(); @Test public void testToBuilder() { compareBucketsNotification(NOTIFICATION, NOTIFICATION.toBuilder().build()); - Notification notification = NOTIFICATION.toBuilder().setGeneratedId("id").build(); - assertEquals("id", notification.getGeneratedId()); - notification = notification.toBuilder().setGeneratedId(GENERATED_ID).build(); + Notification notification = NOTIFICATION.toBuilder().setTopic(TOPIC).build(); + assertEquals(TOPIC, notification.getTopic()); + notification = notification.toBuilder().setTopic(TOPIC).build(); compareBucketsNotification(NOTIFICATION, notification); } @@ -66,12 +65,19 @@ public void testToBuilderIncomplete() { public void testOf() { Notification notification = Notification.of(TOPIC); assertEquals(TOPIC, notification.getTopic()); + assertNull(notification.getGeneratedId()); + assertNull(notification.getCustomAttributes()); + assertNull(notification.getEtag()); + assertNull(notification.getSelfLink()); + assertNull(notification.getEventTypes()); + assertNull(notification.getObjectNamePrefix()); + assertNull(notification.getPayloadFormat()); } @Test public void testBuilder() { assertEquals(ETAG, NOTIFICATION.getEtag()); - assertEquals(GENERATED_ID, NOTIFICATION.getGeneratedId()); + assertNull(NOTIFICATION.getGeneratedId()); assertEquals(SELF_LINK, NOTIFICATION.getSelfLink()); assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION.getObjectNamePrefix()); assertEquals(PAYLOAD_FORMAT, NOTIFICATION.getPayloadFormat()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java index 8dca7ee5b..1072fc204 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java @@ -387,7 +387,6 @@ public long millisTime() { .setEventTypes(EVENT_TYPES) .setObjectNamePrefix(OBJECT_NAME_PREFIX) .setPayloadFormat(PAYLOAD_FORMAT) - .setGeneratedId(GENERATED_ID) .build(); private static final Notification NOTIFICATION_02 = Notification.newBuilder(TOPIC) @@ -397,7 +396,6 @@ public long millisTime() { .setEventTypes(EVENT_TYPES) .setObjectNamePrefix(OBJECT_NAME_PREFIX) .setPayloadFormat(PAYLOAD_FORMAT) - .setGeneratedId(GENERATED_ID) .build(); private static final String ACCOUNT = "account"; @@ -1717,7 +1715,7 @@ public void testDeleteNotification() { } private void compareBucketsNotification(Notification value) { - assertEquals(GENERATED_ID, value.getGeneratedId()); + assertNull(value.getGeneratedId()); assertEquals(CUSTOM_ATTRIBUTES, value.getCustomAttributes()); assertEquals(ETAG, value.getEtag()); assertEquals(SELF_LINK, value.getSelfLink()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index e29703998..eb93a861a 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -254,9 +254,8 @@ public static void beforeClass() throws IOException { // Prepare KMS KeyRing for CMEK tests prepareKmsKeys(); - // Add notification. - topicAdminClient = TopicAdminClient.create(); - addNotification(topicAdminClient); + // Configure topic admin client for notification. + topicAdminClient = configureTopicAdminClient(); } private static void unsetRequesterPays() { @@ -279,9 +278,10 @@ private static void unsetRequesterPays() { public static void afterClass() throws ExecutionException, InterruptedException { if (storage != null) { - /* Delete the specified notification on the specified bucket as well as delete the pubsub topic */ + /* Deletes the pubsub topic */ if (topicAdminClient != null) { - deleteNotification(topicAdminClient); + topicAdminClient.deleteTopic(TOPIC); + topicAdminClient.close(); } // In beforeClass, we make buckets auto-delete blobs older than a day old. // Here, delete all buckets older than 2 days. They should already be empty and easy. @@ -438,7 +438,8 @@ private static String ensureKmsKeyExistsForTests( return kmsKeyResourcePath; } - private static Notification addNotification(TopicAdminClient topicAdminClient) { + private static TopicAdminClient configureTopicAdminClient() throws IOException { + TopicAdminClient topicAdminClient = TopicAdminClient.create(); topicAdminClient.createTopic(TOPIC); GetIamPolicyRequest getIamPolicyRequest = GetIamPolicyRequest.newBuilder().setResource(TOPIC).build(); @@ -451,21 +452,7 @@ private static Notification addNotification(TopicAdminClient topicAdminClient) { .setPolicy(policy.toBuilder().addBindings(binding).build()) .build(); topicAdminClient.setIamPolicy(setIamPolicyRequest); - - // Add a new notification to the bucket. - Notification bucketNotification = - Notification.newBuilder(TOPIC) - .setCustomAttributes(CUSTOM_ATTRIBUTES) - .setPayloadFormat(PAYLOAD_FORMAT) - .build(); - notification = storage.addNotification(BUCKET, bucketNotification); - return notification; - } - - public static void deleteNotification(TopicAdminClient topicAdminClient) { - storage.deleteNotification(BUCKET, notification.getGeneratedId()); - topicAdminClient.deleteTopic(TOPIC); - topicAdminClient.close(); + return topicAdminClient; } @Test(timeout = 5000) @@ -3821,44 +3808,58 @@ public void testRemoveBucketCORS() throws ExecutionException, InterruptedExcepti @Test public void testBucketUpdateTime() throws ExecutionException, InterruptedException { - String bucketName = RemoteStorageHelper.generateBucketName(); - BucketInfo bucketInfo = - BucketInfo.newBuilder(bucketName).setLocation("us").setVersioningEnabled(true).build(); - try { - Bucket bucket = storage.create(bucketInfo); - assertThat(bucket).isNotNull(); - assertThat(bucket.versioningEnabled()).isTrue(); - assertThat(bucket.getCreateTime()).isNotNull(); - assertThat(bucket.getUpdateTime()).isEqualTo(bucket.getCreateTime()); - - Bucket updatedBucket = bucket.toBuilder().setVersioningEnabled(false).build().update(); - assertThat(updatedBucket.versioningEnabled()).isFalse(); - assertThat(updatedBucket.getUpdateTime()).isNotNull(); - assertThat(updatedBucket.getCreateTime()).isEqualTo(bucket.getCreateTime()); - assertThat(updatedBucket.getUpdateTime()).isGreaterThan(bucket.getCreateTime()); - } finally { - RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); - } - } - - @Test - public void testGetNotification() { - Notification actualNotification = - storage.getNotification(BUCKET, notification.getGeneratedId()); - assertEquals(CUSTOM_ATTRIBUTES, actualNotification.getCustomAttributes()); - assertEquals(PAYLOAD_FORMAT.name(), actualNotification.getPayloadFormat().name()); - assertTrue(actualNotification.getTopic().contains(TOPIC)); + String bucketName = RemoteStorageHelper.generateBucketName(); + BucketInfo bucketInfo = + BucketInfo.newBuilder(bucketName).setLocation("us").setVersioningEnabled(true).build(); + try { + Bucket bucket = storage.create(bucketInfo); + assertThat(bucket).isNotNull(); + assertThat(bucket.versioningEnabled()).isTrue(); + assertThat(bucket.getCreateTime()).isNotNull(); + assertThat(bucket.getUpdateTime()).isEqualTo(bucket.getCreateTime()); + + Bucket updatedBucket = bucket.toBuilder().setVersioningEnabled(false).build().update(); + assertThat(updatedBucket.versioningEnabled()).isFalse(); + assertThat(updatedBucket.getUpdateTime()).isNotNull(); + assertThat(updatedBucket.getCreateTime()).isEqualTo(bucket.getCreateTime()); + assertThat(updatedBucket.getUpdateTime()).isGreaterThan(bucket.getCreateTime()); + } finally { + RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); + } } @Test - public void testListNotification() { - List notifications = storage.listNotifications(BUCKET); - for (Notification actualNotification : notifications) { - if (actualNotification.getGeneratedId().equals(notification.getGeneratedId())) { - assertEquals(CUSTOM_ATTRIBUTES, actualNotification.getCustomAttributes()); - assertEquals(PAYLOAD_FORMAT.name(), actualNotification.getPayloadFormat().name()); - assertTrue(actualNotification.getTopic().contains(TOPIC)); - } + public void testNotification() throws InterruptedException, ExecutionException { + String bucketName = RemoteStorageHelper.generateBucketName(); + Bucket bucket = storage.create(BucketInfo.newBuilder(bucketName).setLocation("us").build()); + Notification bucketNotification = + Notification.newBuilder(TOPIC) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setPayloadFormat(PAYLOAD_FORMAT) + .build(); + try { + Notification notification = storage.addNotification(bucketName, bucketNotification); + assertThat(notification.getGeneratedId()).isNotNull(); + assertThat(CUSTOM_ATTRIBUTES).isEqualTo(notification.getCustomAttributes()); + assertThat(PAYLOAD_FORMAT.name()).isEqualTo(notification.getPayloadFormat().name()); + assertThat(notification.getTopic().contains(TOPIC)).isTrue(); + + // Gets the notification with the specified id. + Notification actualNotification = + storage.getNotification(bucketName, notification.getGeneratedId()); + assertEquals(notification, actualNotification); + + // Retrieves the list of notifications associated with the bucket. + List notifications = storage.listNotifications(bucketName); + assertEquals(1, notifications.size()); + + // Deletes the notification with the specified id. + boolean isDeleted = storage.deleteNotification(bucketName, notification.getGeneratedId()); + assertThat(isDeleted).isTrue(); + assertThat(storage.getNotification(bucketName, notification.getGeneratedId())).isNull(); + assertThat(storage.listNotifications(bucketName)).isEmpty(); + } finally { + RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); } } From 296d5e5818051e8adc82952af80ad39574d11aec Mon Sep 17 00:00:00 2001 From: athakor Date: Thu, 16 Jul 2020 14:33:54 +0530 Subject: [PATCH 12/18] feat: add more checks in test --- .../test/java/com/google/cloud/storage/it/ITStorageTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index eb93a861a..fcef2deb2 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -3838,6 +3838,7 @@ public void testNotification() throws InterruptedException, ExecutionException { .setPayloadFormat(PAYLOAD_FORMAT) .build(); try { + assertThat(storage.listNotifications(bucketName)).isEmpty(); Notification notification = storage.addNotification(bucketName, bucketNotification); assertThat(notification.getGeneratedId()).isNotNull(); assertThat(CUSTOM_ATTRIBUTES).isEqualTo(notification.getCustomAttributes()); @@ -3851,7 +3852,9 @@ public void testNotification() throws InterruptedException, ExecutionException { // Retrieves the list of notifications associated with the bucket. List notifications = storage.listNotifications(bucketName); - assertEquals(1, notifications.size()); + assertThat(notifications.size()).isEqualTo(1); + assertThat(notifications.get(0).getGeneratedId()) + .isEqualTo(actualNotification.getGeneratedId()); // Deletes the notification with the specified id. boolean isDeleted = storage.deleteNotification(bucketName, notification.getGeneratedId()); From 9723a5449d5e54d88865a87299fa44327871398b Mon Sep 17 00:00:00 2001 From: athakor Date: Thu, 16 Jul 2020 15:59:06 +0530 Subject: [PATCH 13/18] feat: updated checks --- .../test/java/com/google/cloud/storage/it/ITStorageTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index fcef2deb2..74ba32b2a 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -3857,8 +3857,8 @@ public void testNotification() throws InterruptedException, ExecutionException { .isEqualTo(actualNotification.getGeneratedId()); // Deletes the notification with the specified id. - boolean isDeleted = storage.deleteNotification(bucketName, notification.getGeneratedId()); - assertThat(isDeleted).isTrue(); + assertThat(storage.deleteNotification(bucketName, notification.getGeneratedId())).isTrue(); + assertThat(storage.deleteNotification(bucketName, notification.getGeneratedId())).isFalse(); assertThat(storage.getNotification(bucketName, notification.getGeneratedId())).isNull(); assertThat(storage.listNotifications(bucketName)).isEmpty(); } finally { From a4bdc42699975bbe9abaaaa04082f090b38dcd34 Mon Sep 17 00:00:00 2001 From: athakor Date: Fri, 24 Jul 2020 17:38:05 +0530 Subject: [PATCH 14/18] feat: address the additional comments --- .../clirr-ignored-differences.xml | 10 +- .../google/cloud/storage/Notification.java | 300 +++------------ .../cloud/storage/NotificationInfo.java | 362 ++++++++++++++++++ .../com/google/cloud/storage/Storage.java | 10 +- .../com/google/cloud/storage/StorageImpl.java | 19 +- .../cloud/storage/NotificationInfoTest.java | 110 ++++++ .../cloud/storage/NotificationTest.java | 109 +++--- .../cloud/storage/StorageImplMockitoTest.java | 26 +- .../cloud/storage/it/ITStorageTest.java | 23 +- 9 files changed, 641 insertions(+), 328 deletions(-) create mode 100644 google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java create mode 100644 google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml index 73a70b8f0..f387cdfe9 100644 --- a/google-cloud-storage/clirr-ignored-differences.xml +++ b/google-cloud-storage/clirr-ignored-differences.xml @@ -13,27 +13,27 @@
com/google/cloud/storage/Storage - com.google.cloud.storage.Notification addNotification(java.lang.String, com.google.cloud.storage.Notification) + *.Notification addNotification(*.String, *.NotificationInfo) 7012 com/google/cloud/storage/Storage - com.google.cloud.storage.Notification getNotification(java.lang.String, java.lang.String) + *.Notification getNotification(*.String, *.String) 7012 com/google/cloud/storage/Storage - java.util.List listNotifications(java.lang.String) + java.util.List listNotifications(*.String) 7012 com/google/cloud/storage/Storage - boolean deleteNotification(java.lang.String, java.lang.String) + boolean deleteNotification(*.String, *.String) 7012 com/google/cloud/storage/spi/v1/StorageRpc - com.google.api.services.storage.model.Notification getNotification(java.lang.String, java.lang.String) + *.model.Notification getNotification(*.String, *.String) 7012 diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java index f1bf9ded1..2a62137b9 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -17,14 +17,6 @@ import static com.google.common.base.Preconditions.checkNotNull; -import com.google.api.pathtemplate.PathTemplate; -import com.google.common.base.Function; -import com.google.common.base.MoreObjects; -import com.google.common.collect.ImmutableMap; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.Objects; @@ -33,299 +25,115 @@ * href="https://cloud.google.com/storage/docs/pubsub-notifications">pubsub-notifications for * details. */ -public class Notification implements Serializable { +public class Notification extends NotificationInfo { - private static final long serialVersionUID = 5725883368559753810L; - private static final PathTemplate PATH_TEMPLATE = - PathTemplate.createWithoutUrlEncoding("projects/{project}/topics/{topic}"); - - public enum PayloadFormat { - JSON_API_V1, - NONE - } - - public enum EventType { - OBJECT_FINALIZE, - OBJECT_METADATA_UPDATE, - OBJECT_DELETE, - OBJECT_ARCHIVE - } - - static final Function - FROM_PB_FUNCTION = - new Function() { - @Override - public Notification apply(com.google.api.services.storage.model.Notification pb) { - return Notification.fromPb(pb); - } - }; - static final Function - TO_PB_FUNCTION = - new Function() { - @Override - public com.google.api.services.storage.model.Notification apply( - Notification notification) { - return notification.toPb(); - } - }; - private final String generatedId; - private final String topic; - private final List eventTypes; - private final Map customAttributes; - private final PayloadFormat payloadFormat; - private final String objectNamePrefix; - private final String etag; - private final String selfLink; + private final StorageOptions options; + private transient Storage storage; /** Builder for {@code Notification}. */ - public static class Builder { - - private String generatedId; - private String topic; - private List eventTypes; - private Map customAttributes; - private PayloadFormat payloadFormat; - private String objectNamePrefix; - private String etag; - private String selfLink; + public static class Builder extends NotificationInfo.Builder { + private final Storage storage; + private final NotificationInfo.BuilderImpl infoBuilder; - private Builder(String topic) { - this.topic = topic; + Builder(Notification notification) { + this.storage = notification.storage; + this.infoBuilder = new NotificationInfo.BuilderImpl(notification); } - private Builder(Notification notification) { - generatedId = notification.generatedId; - etag = notification.etag; - selfLink = notification.selfLink; - topic = notification.topic; - eventTypes = notification.eventTypes; - customAttributes = notification.customAttributes; - payloadFormat = notification.payloadFormat; - objectNamePrefix = notification.objectNamePrefix; - } - - private Builder setGeneratedId(String generatedId) { - this.generatedId = generatedId; + @Override + Builder setGeneratedId(String generatedId) { + infoBuilder.setGeneratedId(generatedId); return this; } + @Override public Builder setSelfLink(String selfLink) { - this.selfLink = selfLink; + infoBuilder.setSelfLink(selfLink); return this; } - /** Sets a topic in the format of "projects/{project}/topics/{topic}". */ + @Override public Builder setTopic(String topic) { - this.topic = topic; + infoBuilder.setTopic(topic); return this; } + @Override public Builder setPayloadFormat(PayloadFormat payloadFormat) { - this.payloadFormat = payloadFormat; + infoBuilder.setPayloadFormat(payloadFormat); return this; } + @Override public Builder setObjectNamePrefix(String objectNamePrefix) { - this.objectNamePrefix = objectNamePrefix; + infoBuilder.setObjectNamePrefix(objectNamePrefix); return this; } + @Override public Builder setEventTypes(EventType... eventTypes) { - this.eventTypes = eventTypes != null ? Arrays.asList(eventTypes) : null; + infoBuilder.setEventTypes(eventTypes); return this; } + @Override public Builder setEtag(String etag) { - this.etag = etag; + infoBuilder.setEtag(etag); return this; } + @Override public Builder setCustomAttributes(Map customAttributes) { - this.customAttributes = - customAttributes != null ? ImmutableMap.copyOf(customAttributes) : null; + infoBuilder.setCustomAttributes(customAttributes); return this; } + @Override public Notification build() { - checkNotNull(topic); - checkTopicFormat(topic); - return new Notification(this); + return new Notification(storage, infoBuilder); } } - private Notification(Builder builder) { - generatedId = builder.generatedId; - etag = builder.etag; - selfLink = builder.selfLink; - topic = builder.topic; - eventTypes = builder.eventTypes; - customAttributes = builder.customAttributes; - payloadFormat = builder.payloadFormat; - objectNamePrefix = builder.objectNamePrefix; - } - - /** Returns the service-generated id for the notification. */ - public String getGeneratedId() { - return generatedId; - } - - /** Returns the topic in Pub/Sub that receives notifications. */ - public String getTopic() { - return topic; + Notification(Storage storage, NotificationInfo.BuilderImpl infoBuilder) { + super(infoBuilder); + this.storage = checkNotNull(storage); + this.options = storage.getOptions(); } - /** Returns the canonical URI of this topic as a string. */ - public String getSelfLink() { - return selfLink; - } - - /** Returns the desired content of the Payload. */ - public PayloadFormat getPayloadFormat() { - return payloadFormat; - } - - /** Returns the object name prefix for which this notification configuration applies. */ - public String getObjectNamePrefix() { - return objectNamePrefix; - } - - /** - * Returns HTTP 1.1 Entity tag for the notification. See Entity Tags - */ - public String getEtag() { - return etag; - } - - /** - * Returns the events that trigger a notification to be sent. If empty, notifications are - * triggered by any event. See Event types to get - * list of available events. - */ - public List getEventTypes() { - return eventTypes; - } - - /** - * Returns the list of additional attributes to attach to each Cloud PubSub message published for - * this notification subscription. - */ - public Map getCustomAttributes() { - return customAttributes; + /** Returns the notification's {@code Storage} object used to issue requests. */ + public Storage getStorage() { + return storage; } @Override - public int hashCode() { - return toPb().hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj == this - || obj != null - && obj.getClass().equals(Notification.class) - && Objects.equals(toPb(), ((Notification) obj).toPb()); + public Builder toBuilder() { + return new Notification.Builder(this); } @Override - public String toString() { - return MoreObjects.toStringHelper(this).add("topic", getTopic()).toString(); - } - - com.google.api.services.storage.model.Notification toPb() { - com.google.api.services.storage.model.Notification notificationPb = - new com.google.api.services.storage.model.Notification(); - notificationPb.setId(generatedId); - notificationPb.setEtag(etag); - if (customAttributes != null) { - notificationPb.setCustomAttributes(customAttributes); - } - if (eventTypes != null && eventTypes.size() > 0) { - List eventTypesPb = new ArrayList<>(); - for (EventType eventType : eventTypes) { - eventTypesPb.add(eventType.toString()); - } - notificationPb.setEventTypes(eventTypesPb); + public boolean equals(Object o) { + if (this == o) { + return true; } - if (objectNamePrefix != null) { - notificationPb.setObjectNamePrefix(objectNamePrefix); + if (o == null || getClass() != o.getClass()) { + return false; } - if (payloadFormat != null) { - notificationPb.setPayloadFormat(payloadFormat.toString()); - } else { - notificationPb.setPayloadFormat(PayloadFormat.NONE.toString()); + if (!super.equals(o)) { + return false; } - notificationPb.setSelfLink(selfLink); - notificationPb.setTopic(topic); - - return notificationPb; - } - - /** - * Creates a {@code Notification} object for the provided topic. - * - *

Example of creating the notification object: - * - *

{@code
-   * String topic = "projects/myProject/topics/myTopic"
-   * Notification notification = Notification.of(topic)
-   * }
- * - * @param topic a string in the format "projects/{project}/topics/{topic}" - */ - public static Notification of(String topic) { - checkTopicFormat(topic); - return newBuilder(topic).build(); - } - - /** Returns a builder for the current notification. */ - public Builder toBuilder() { - return new Builder(this); + Notification notification = (Notification) o; + return Objects.equals(toPb(), notification.toPb()) + && Objects.equals(options, notification.options); } - /** - * Returns a {@code Notification.Builder} with the topic set. - * - * @param topic a string in the format "projects/{project}/topics/{topic}" - */ - public static Builder newBuilder(String topic) { - checkTopicFormat(topic); - return new Builder(topic); - } - - static Notification fromPb(com.google.api.services.storage.model.Notification notificationPb) { - Builder builder = newBuilder(notificationPb.getTopic()); - if (notificationPb.getId() != null) { - builder.setGeneratedId(notificationPb.getId()); - } - if (notificationPb.getEtag() != null) { - builder.setEtag(notificationPb.getEtag()); - } - if (notificationPb.getCustomAttributes() != null) { - builder.setCustomAttributes(notificationPb.getCustomAttributes()); - } - if (notificationPb.getSelfLink() != null) { - builder.setSelfLink(notificationPb.getSelfLink()); - } - if (notificationPb.getObjectNamePrefix() != null) { - builder.setObjectNamePrefix(notificationPb.getObjectNamePrefix()); - } - if (notificationPb.getEventTypes() != null) { - List eventTypesPb = notificationPb.getEventTypes(); - EventType[] eventTypes = new EventType[eventTypesPb.size()]; - for (int index = 0; index < eventTypesPb.size(); index++) { - eventTypes[index] = EventType.valueOf(eventTypesPb.get(index)); - } - builder.setEventTypes(eventTypes); - } - if (notificationPb.getPayloadFormat() != null) { - builder.setPayloadFormat(PayloadFormat.valueOf(notificationPb.getPayloadFormat())); - } - return builder.build(); + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), options, storage); } - private static void checkTopicFormat(String topic) { - PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); + static Notification fromPb( + Storage storage, com.google.api.services.storage.model.Notification notificationPb) { + return new Notification( + storage, new NotificationInfo.BuilderImpl(NotificationInfo.fromPb(notificationPb))); } } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java new file mode 100644 index 000000000..ff0528661 --- /dev/null +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java @@ -0,0 +1,362 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.storage; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.api.pathtemplate.PathTemplate; +import com.google.common.base.Function; +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableMap; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** The class representing Pub/Sub Notification metadata for the Storage. */ +public class NotificationInfo implements Serializable { + + private static final long serialVersionUID = 5725883368559753810L; + private static final PathTemplate PATH_TEMPLATE = + PathTemplate.createWithoutUrlEncoding("projects/{project}/topics/{topic}"); + static final Function + FROM_PB_FUNCTION = + new Function() { + @Override + public NotificationInfo apply(com.google.api.services.storage.model.Notification pb) { + return NotificationInfo.fromPb(pb); + } + }; + static final Function + TO_PB_FUNCTION = + new Function() { + @Override + public com.google.api.services.storage.model.Notification apply( + NotificationInfo NotificationInfo) { + return NotificationInfo.toPb(); + } + }; + + public enum PayloadFormat { + JSON_API_V1, + NONE + } + + public enum EventType { + OBJECT_FINALIZE, + OBJECT_METADATA_UPDATE, + OBJECT_DELETE, + OBJECT_ARCHIVE + } + + private final String generatedId; + private final String topic; + private final List eventTypes; + private final Map customAttributes; + private final PayloadFormat payloadFormat; + private final String objectNamePrefix; + private final String etag; + private final String selfLink; + + /** Builder for {@code NotificationInfo}. */ + public abstract static class Builder { + Builder() {} + + abstract Builder setGeneratedId(String generatedId); + + public abstract Builder setSelfLink(String selfLink); + + public abstract Builder setTopic(String topic); + + public abstract Builder setPayloadFormat(PayloadFormat payloadFormat); + + public abstract Builder setObjectNamePrefix(String objectNamePrefix); + + public abstract Builder setEventTypes(EventType... eventTypes); + + public abstract Builder setEtag(String etag); + + public abstract Builder setCustomAttributes(Map customAttributes); + + /** Creates a {@code NotificationInfo} object. */ + public abstract NotificationInfo build(); + } + + /** Builder for {@code NotificationInfo}. */ + public static class BuilderImpl extends Builder { + + private String generatedId; + private String topic; + private List eventTypes; + private Map customAttributes; + private PayloadFormat payloadFormat; + private String objectNamePrefix; + private String etag; + private String selfLink; + + BuilderImpl(String topic) { + this.topic = topic; + } + + BuilderImpl(NotificationInfo notificationInfo) { + generatedId = notificationInfo.generatedId; + etag = notificationInfo.etag; + selfLink = notificationInfo.selfLink; + topic = notificationInfo.topic; + eventTypes = notificationInfo.eventTypes; + customAttributes = notificationInfo.customAttributes; + payloadFormat = notificationInfo.payloadFormat; + objectNamePrefix = notificationInfo.objectNamePrefix; + } + + @Override + Builder setGeneratedId(String generatedId) { + this.generatedId = generatedId; + return this; + } + + @Override + public Builder setSelfLink(String selfLink) { + this.selfLink = selfLink; + return this; + } + + /** Sets a topic in the format of "projects/{project}/topics/{topic}". */ + @Override + public Builder setTopic(String topic) { + this.topic = topic; + return this; + } + + @Override + public Builder setPayloadFormat(PayloadFormat payloadFormat) { + this.payloadFormat = payloadFormat; + return this; + } + + @Override + public Builder setObjectNamePrefix(String objectNamePrefix) { + this.objectNamePrefix = objectNamePrefix; + return this; + } + + @Override + public Builder setEventTypes(EventType... eventTypes) { + this.eventTypes = eventTypes != null ? Arrays.asList(eventTypes) : null; + return this; + } + + @Override + public Builder setEtag(String etag) { + this.etag = etag; + return this; + } + + @Override + public Builder setCustomAttributes(Map customAttributes) { + this.customAttributes = + customAttributes != null ? ImmutableMap.copyOf(customAttributes) : null; + return this; + } + + public NotificationInfo build() { + checkNotNull(topic); + checkTopicFormat(topic); + return new NotificationInfo(this); + } + } + + NotificationInfo(BuilderImpl builder) { + generatedId = builder.generatedId; + etag = builder.etag; + selfLink = builder.selfLink; + topic = builder.topic; + eventTypes = builder.eventTypes; + customAttributes = builder.customAttributes; + payloadFormat = builder.payloadFormat; + objectNamePrefix = builder.objectNamePrefix; + } + + /** Returns the service-generated id for the notification. */ + public String getGeneratedId() { + return generatedId; + } + + /** Returns the topic in Pub/Sub that receives notifications. */ + public String getTopic() { + return topic; + } + + /** Returns the canonical URI of this topic as a string. */ + public String getSelfLink() { + return selfLink; + } + + /** Returns the desired content of the Payload. */ + public NotificationInfo.PayloadFormat getPayloadFormat() { + return payloadFormat; + } + + /** Returns the object name prefix for which this notification configuration applies. */ + public String getObjectNamePrefix() { + return objectNamePrefix; + } + + /** + * Returns HTTP 1.1 Entity tag for the notification. See Entity Tags + */ + public String getEtag() { + return etag; + } + + /** + * Returns the events that trigger a notification to be sent. If empty, notifications are + * triggered by any event. See Event types to get + * list of available events. + */ + public List getEventTypes() { + return eventTypes; + } + + /** + * Returns the list of additional attributes to attach to each Cloud PubSub message published for + * this notification subscription. + */ + public Map getCustomAttributes() { + return customAttributes; + } + + @Override + public int hashCode() { + return toPb().hashCode(); + } + + @Override + public boolean equals(Object obj) { + return obj == this + || obj != null + && obj.getClass().equals(NotificationInfo.class) + && Objects.equals(toPb(), ((NotificationInfo) obj).toPb()); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("topic", topic).toString(); + } + + com.google.api.services.storage.model.Notification toPb() { + com.google.api.services.storage.model.Notification notificationPb = + new com.google.api.services.storage.model.Notification(); + if (generatedId != null) { + notificationPb.setId(generatedId); + } + notificationPb.setEtag(etag); + if (customAttributes != null) { + notificationPb.setCustomAttributes(customAttributes); + } + if (eventTypes != null && eventTypes.size() > 0) { + List eventTypesPb = new ArrayList<>(); + for (EventType eventType : eventTypes) { + eventTypesPb.add(eventType.toString()); + } + notificationPb.setEventTypes(eventTypesPb); + } + if (objectNamePrefix != null) { + notificationPb.setObjectNamePrefix(objectNamePrefix); + } + if (payloadFormat != null) { + notificationPb.setPayloadFormat(payloadFormat.toString()); + } else { + notificationPb.setPayloadFormat(PayloadFormat.NONE.toString()); + } + notificationPb.setSelfLink(selfLink); + notificationPb.setTopic(topic); + + return notificationPb; + } + + /** + * Creates a {@code NotificationInfo} object for the provided topic. + * + *

Example of creating the NotificationInfo object: + * + *

{@code
+   * String topic = "projects/myProject/topics/myTopic"
+   * NotificationInfo notificationInfo = NotificationInfo.of(topic)
+   * }
+ * + * @param topic a string in the format "projects/{project}/topics/{topic}" + */ + public static NotificationInfo of(String topic) { + checkTopicFormat(topic); + return newBuilder(topic).build(); + } + /** + * Creates a {@code NotificationInfo} object for the provided topic. + * + * @param topic a string in the format "projects/{project}/topics/{topic}" + */ + public static Builder newBuilder(String topic) { + checkTopicFormat(topic); + return new BuilderImpl(topic); + } + + /** Returns a builder for the current notification. */ + public Builder toBuilder() { + return new BuilderImpl(this); + } + + static NotificationInfo fromPb( + com.google.api.services.storage.model.Notification notificationPb) { + NotificationInfo.Builder builder = new NotificationInfo.BuilderImpl(notificationPb.getTopic()); + if (notificationPb.getId() != null) { + builder.setGeneratedId(notificationPb.getId()); + } + if (notificationPb.getEtag() != null) { + builder.setEtag(notificationPb.getEtag()); + } + if (notificationPb.getCustomAttributes() != null) { + builder.setCustomAttributes(notificationPb.getCustomAttributes()); + } + if (notificationPb.getSelfLink() != null) { + builder.setSelfLink(notificationPb.getSelfLink()); + } + if (notificationPb.getObjectNamePrefix() != null) { + builder.setObjectNamePrefix(notificationPb.getObjectNamePrefix()); + } + if (notificationPb.getEventTypes() != null) { + List eventTypesPb = notificationPb.getEventTypes(); + EventType[] eventTypes = new EventType[eventTypesPb.size()]; + for (int index = 0; index < eventTypesPb.size(); index++) { + eventTypes[index] = EventType.valueOf(eventTypesPb.get(index)); + } + builder.setEventTypes(eventTypes); + } + if (notificationPb.getPayloadFormat() != null) { + builder.setPayloadFormat(PayloadFormat.valueOf(notificationPb.getPayloadFormat())); + } + return builder.build(); + } + + private static void checkTopicFormat(String topic) { + PATH_TEMPLATE.validatedMatch(topic, "topic name must be in valid format"); + } +} diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index bb97c66c0..df03eccfb 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3634,20 +3634,20 @@ List testIamPermissions( *
{@code
    * String bucketName = "my-unique-bucket";
    * String topic = "projects/myProject/topics/myTopic"
-   * Notification bucketNotification = Notification.newBuilder(topic)
+   * NotificationInfo notificationInfo = NotificationInfo.newBuilder(topic)
    *  .setCustomAttributes(ImmutableMap.of("label1", "value1"))
-   *  .setEventTypes(Notification.EventType.OBJECT_FINALIZE)
+   *  .setEventTypes(NotificationInfo.EventType.OBJECT_FINALIZE)
    *  .setPayloadFormat(Notification.PayloadFormat.JSON_API_V1)
    *  .build();
-   * Notification notification = storage.addNotification(bucketName, bucketNotification);
+   * Notification notification = storage.addNotification(bucketName, notificationInfo);
    * }
* * @param bucket name of the bucket - * @param notification a {@code Notification} object + * @param notificationInfo notification to create * @return the created notification * @throws StorageException upon failure */ - Notification addNotification(String bucket, Notification notification); + Notification addNotification(String bucket, NotificationInfo notificationInfo); /** * Gets the notification with the specified id. diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index 503347d4e..a1315877f 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -1375,10 +1375,13 @@ private U run(ResultRetryAlgorithm algorithm, Callable c, Function< } @Override - public Notification addNotification(final String bucket, final Notification notification) { - final com.google.api.services.storage.model.Notification notificationPb = notification.toPb(); + public Notification addNotification( + final String bucket, final NotificationInfo notificationInfo) { + final com.google.api.services.storage.model.Notification notificationPb = + notificationInfo.toPb(); try { return Notification.fromPb( + this, runWithRetries( new Callable() { @Override @@ -1408,7 +1411,7 @@ public com.google.api.services.storage.model.Notification call() { getOptions().getRetrySettings(), EXCEPTION_HANDLER, getOptions().getClock()); - return answer == null ? null : Notification.fromPb(answer); + return answer == null ? null : Notification.fromPb(this, answer); } catch (RetryHelperException e) { throw StorageException.translateAndThrow(e); } @@ -1430,7 +1433,15 @@ public List call() { getOptions().getClock()); return answer == null ? ImmutableList.of() - : Lists.transform(answer, Notification.FROM_PB_FUNCTION); + : Lists.transform( + answer, + new Function() { + @Override + public Notification apply( + com.google.api.services.storage.model.Notification notificationPb) { + return Notification.fromPb(getOptions().getService(), notificationPb); + } + }); } catch (RetryHelperException e) { throw StorageException.translateAndThrow(e); } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java new file mode 100644 index 000000000..0b889b69d --- /dev/null +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java @@ -0,0 +1,110 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.storage; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import com.google.cloud.storage.NotificationInfo.EventType; +import com.google.cloud.storage.NotificationInfo.PayloadFormat; +import com.google.common.collect.ImmutableMap; +import java.util.Arrays; +import java.util.Map; +import org.junit.Test; + +public class NotificationInfoTest { + private static final String ETAG = "0xFF00"; + private static final String SELF_LINK = "http://storage/b/n"; + private static final String OBJECT_NAME_PREFIX = "index.html"; + private static final String TOPIC = "projects/myProject/topics/topic1"; + private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); + private static final PayloadFormat PAYLOAD_FORMAT = PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final EventType[] EVENT_TYPES = { + EventType.OBJECT_FINALIZE, EventType.OBJECT_METADATA_UPDATE + }; + private static final NotificationInfo NOTIFICATION_INFO = + NotificationInfo.newBuilder(TOPIC) + .setEtag(ETAG) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setSelfLink(SELF_LINK) + .setEventTypes(EVENT_TYPES) + .setObjectNamePrefix(OBJECT_NAME_PREFIX) + .setPayloadFormat(PAYLOAD_FORMAT) + .build(); + + @Test + public void testToBuilder() { + compareBucketsNotification(NOTIFICATION_INFO, NOTIFICATION_INFO.toBuilder().build()); + NotificationInfo notificationInfo = NOTIFICATION_INFO.toBuilder().setTopic(TOPIC).build(); + assertEquals(TOPIC, notificationInfo.getTopic()); + notificationInfo = notificationInfo.toBuilder().setTopic(TOPIC).build(); + compareBucketsNotification(NOTIFICATION_INFO, notificationInfo); + } + + @Test + public void testToBuilderIncomplete() { + NotificationInfo incompleteNotificationInfo = Notification.newBuilder(TOPIC).build(); + compareBucketsNotification( + incompleteNotificationInfo, incompleteNotificationInfo.toBuilder().build()); + } + + @Test + public void testOf() { + NotificationInfo notificationInfo = NotificationInfo.of(TOPIC); + assertEquals(TOPIC, notificationInfo.getTopic()); + assertNull(notificationInfo.getGeneratedId()); + assertNull(notificationInfo.getCustomAttributes()); + assertNull(notificationInfo.getEtag()); + assertNull(notificationInfo.getSelfLink()); + assertNull(notificationInfo.getEventTypes()); + assertNull(notificationInfo.getObjectNamePrefix()); + assertNull(notificationInfo.getPayloadFormat()); + } + + @Test + public void testBuilder() { + assertEquals(ETAG, NOTIFICATION_INFO.getEtag()); + assertNull(NOTIFICATION_INFO.getGeneratedId()); + assertEquals(SELF_LINK, NOTIFICATION_INFO.getSelfLink()); + assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION_INFO.getObjectNamePrefix()); + assertEquals(PAYLOAD_FORMAT, NOTIFICATION_INFO.getPayloadFormat()); + assertEquals(TOPIC, NOTIFICATION_INFO.getTopic()); + assertEquals(CUSTOM_ATTRIBUTES, NOTIFICATION_INFO.getCustomAttributes()); + assertEquals(Arrays.asList(EVENT_TYPES), NOTIFICATION_INFO.getEventTypes()); + } + + @Test + public void testToPbAndFromPb() { + compareBucketsNotification( + NOTIFICATION_INFO, NotificationInfo.fromPb(NOTIFICATION_INFO.toPb())); + NotificationInfo notificationInfo = + NotificationInfo.of(TOPIC).toBuilder().setPayloadFormat(PayloadFormat.NONE).build(); + compareBucketsNotification(notificationInfo, Notification.fromPb(notificationInfo.toPb())); + } + + private void compareBucketsNotification(NotificationInfo expected, NotificationInfo actual) { + assertEquals(expected, actual); + assertEquals(expected.getGeneratedId(), actual.getGeneratedId()); + assertEquals(expected.getCustomAttributes(), actual.getCustomAttributes()); + assertEquals(expected.getEtag(), actual.getEtag()); + assertEquals(expected.getSelfLink(), actual.getSelfLink()); + assertEquals(expected.getEventTypes(), actual.getEventTypes()); + assertEquals(expected.getObjectNamePrefix(), actual.getObjectNamePrefix()); + assertEquals(expected.getPayloadFormat(), actual.getPayloadFormat()); + assertEquals(expected.getTopic(), actual.getTopic()); + } +} diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java index 580ec7f82..2c89a5157 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java @@ -16,28 +16,38 @@ package com.google.cloud.storage; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createStrictMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; +import com.google.cloud.storage.NotificationInfo.EventType; +import com.google.cloud.storage.NotificationInfo.PayloadFormat; import com.google.common.collect.ImmutableMap; import java.util.Arrays; import java.util.Map; +import org.junit.After; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +@RunWith(JUnit4.class) public class NotificationTest { private static final String ETAG = "0xFF00"; private static final String SELF_LINK = "http://storage/b/n"; - private static final Notification.EventType[] EVENT_TYPES = { - Notification.EventType.OBJECT_FINALIZE, Notification.EventType.OBJECT_METADATA_UPDATE - }; private static final String OBJECT_NAME_PREFIX = "index.html"; - private static final Notification.PayloadFormat PAYLOAD_FORMAT = - Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; private static final String TOPIC = "projects/myProject/topics/topic1"; private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); - private static final Notification NOTIFICATION = - Notification.newBuilder(TOPIC) + private static final PayloadFormat PAYLOAD_FORMAT = PayloadFormat.JSON_API_V1.JSON_API_V1; + private static final EventType[] EVENT_TYPES = { + EventType.OBJECT_FINALIZE, EventType.OBJECT_METADATA_UPDATE + }; + private static final NotificationInfo NOTIFICATION_INFO = + NotificationInfo.newBuilder(TOPIC) .setEtag(ETAG) .setCustomAttributes(CUSTOM_ATTRIBUTES) .setSelfLink(SELF_LINK) @@ -46,59 +56,62 @@ public class NotificationTest { .setPayloadFormat(PAYLOAD_FORMAT) .build(); - @Test - public void testToBuilder() { - compareBucketsNotification(NOTIFICATION, NOTIFICATION.toBuilder().build()); - Notification notification = NOTIFICATION.toBuilder().setTopic(TOPIC).build(); - assertEquals(TOPIC, notification.getTopic()); - notification = notification.toBuilder().setTopic(TOPIC).build(); - compareBucketsNotification(NOTIFICATION, notification); + private Storage storage; + private StorageOptions mockOptions = createMock(StorageOptions.class); + + @Before + public void setUp() { + storage = createStrictMock(Storage.class); } - @Test - public void testToBuilderIncomplete() { - Notification incompleteNotification = Notification.newBuilder(TOPIC).build(); - compareBucketsNotification(incompleteNotification, incompleteNotification.toBuilder().build()); + @After + public void tearDown() { + verify(storage); } @Test - public void testOf() { - Notification notification = Notification.of(TOPIC); + public void testBuilder() { + expect(storage.getOptions()).andReturn(mockOptions).times(2); + replay(storage); + Notification.Builder builder = + new Notification.Builder( + new Notification(storage, new NotificationInfo.BuilderImpl(NOTIFICATION_INFO))); + Notification notification = + builder + .setEtag(ETAG) + .setCustomAttributes(CUSTOM_ATTRIBUTES) + .setSelfLink(SELF_LINK) + .setEventTypes(EVENT_TYPES) + .setObjectNamePrefix(OBJECT_NAME_PREFIX) + .setPayloadFormat(PAYLOAD_FORMAT) + .build(); + assertEquals(ETAG, notification.getEtag()); + assertEquals(SELF_LINK, notification.getSelfLink()); + assertEquals(OBJECT_NAME_PREFIX, notification.getObjectNamePrefix()); + assertEquals(PAYLOAD_FORMAT, notification.getPayloadFormat()); assertEquals(TOPIC, notification.getTopic()); - assertNull(notification.getGeneratedId()); - assertNull(notification.getCustomAttributes()); - assertNull(notification.getEtag()); - assertNull(notification.getSelfLink()); - assertNull(notification.getEventTypes()); - assertNull(notification.getObjectNamePrefix()); - assertNull(notification.getPayloadFormat()); + assertEquals(CUSTOM_ATTRIBUTES, notification.getCustomAttributes()); + assertEquals(Arrays.asList(EVENT_TYPES), notification.getEventTypes()); } @Test - public void testBuilder() { - assertEquals(ETAG, NOTIFICATION.getEtag()); - assertNull(NOTIFICATION.getGeneratedId()); - assertEquals(SELF_LINK, NOTIFICATION.getSelfLink()); - assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION.getObjectNamePrefix()); - assertEquals(PAYLOAD_FORMAT, NOTIFICATION.getPayloadFormat()); - assertEquals(TOPIC, NOTIFICATION.getTopic()); - assertEquals(CUSTOM_ATTRIBUTES, NOTIFICATION.getCustomAttributes()); - assertEquals(Arrays.asList(EVENT_TYPES), NOTIFICATION.getEventTypes()); + public void testToBuilder() { + expect(storage.getOptions()).andReturn(mockOptions).times(2); + replay(storage); + Notification notification = + new Notification(storage, new NotificationInfo.BuilderImpl(NOTIFICATION_INFO)); + compareBucketNotification(notification, notification.toBuilder().build()); } @Test - public void testToPbAndFromPb() { - compareBucketsNotification(NOTIFICATION, Notification.fromPb(NOTIFICATION.toPb())); - Notification notification = - Notification.of(TOPIC) - .toBuilder() - .setPayloadFormat(Notification.PayloadFormat.NONE) - .build(); - compareBucketsNotification(notification, Notification.fromPb(notification.toPb())); + public void testFromPb() { + expect(storage.getOptions()).andReturn(mockOptions).times(1); + replay(storage); + compareBucketNotification( + NOTIFICATION_INFO, Notification.fromPb(storage, NOTIFICATION_INFO.toPb())); } - private void compareBucketsNotification(Notification expected, Notification actual) { - assertEquals(expected, actual); + private void compareBucketNotification(NotificationInfo expected, NotificationInfo actual) { assertEquals(expected.getGeneratedId(), actual.getGeneratedId()); assertEquals(expected.getCustomAttributes(), actual.getCustomAttributes()); assertEquals(expected.getEtag(), actual.getEtag()); @@ -106,6 +119,6 @@ private void compareBucketsNotification(Notification expected, Notification actu assertEquals(expected.getEventTypes(), actual.getEventTypes()); assertEquals(expected.getObjectNamePrefix(), actual.getObjectNamePrefix()); assertEquals(expected.getPayloadFormat(), actual.getPayloadFormat()); - assertEquals(expected.getTopic(), actual.getTopic()); + assertEquals(expected.getTopic().trim(), actual.getTopic().trim()); } } diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java index 1072fc204..72b8a9b49 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java @@ -379,8 +379,8 @@ public long millisTime() { Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; private static final String TOPIC = "projects/myProject/topics/topic1"; private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); - private static final Notification NOTIFICATION_01 = - Notification.newBuilder(TOPIC) + private static final NotificationInfo NOTIFICATION_INFO_01 = + NotificationInfo.newBuilder(TOPIC) .setEtag(ETAG) .setCustomAttributes(CUSTOM_ATTRIBUTES) .setSelfLink(SELF_LINK) @@ -388,8 +388,8 @@ public long millisTime() { .setObjectNamePrefix(OBJECT_NAME_PREFIX) .setPayloadFormat(PAYLOAD_FORMAT) .build(); - private static final Notification NOTIFICATION_02 = - Notification.newBuilder(TOPIC) + private static final NotificationInfo NOTIFICATION_INFO_02 = + NotificationInfo.newBuilder(TOPIC) .setEtag(ETAG) .setCustomAttributes(CUSTOM_ATTRIBUTES) .setSelfLink(SELF_LINK) @@ -1678,32 +1678,34 @@ public void testWriterFailure() { @Test public void testAddNotification() { - doReturn(NOTIFICATION_01.toPb()) + doReturn(NOTIFICATION_INFO_01.toPb()) .when(storageRpcMock) - .createNotification(BUCKET_NAME1, NOTIFICATION_01.toPb()); + .createNotification(BUCKET_NAME1, NOTIFICATION_INFO_01.toPb()); initializeService(); - Notification notification = storage.addNotification(BUCKET_NAME1, NOTIFICATION_01); - compareBucketsNotification(notification); + Notification notification = storage.addNotification(BUCKET_NAME1, NOTIFICATION_INFO_01); + verifyBucketNotification(notification); } @Test public void testGetNotification() { - doReturn(NOTIFICATION_01.toPb()) + doReturn(NOTIFICATION_INFO_01.toPb()) .when(storageRpcMock) .getNotification(BUCKET_NAME1, GENERATED_ID); initializeService(); Notification notification = storage.getNotification(BUCKET_NAME1, GENERATED_ID); - compareBucketsNotification(notification); + verifyBucketNotification(notification); } @Test public void testListNotification() { - doReturn(Arrays.asList(NOTIFICATION_01.toPb(), NOTIFICATION_02.toPb())) + doReturn(Arrays.asList(NOTIFICATION_INFO_01.toPb(), NOTIFICATION_INFO_02.toPb())) .when(storageRpcMock) .listNotifications(BUCKET_NAME1); initializeService(); List notifications = storage.listNotifications(BUCKET_NAME1); assertEquals(2, notifications.size()); + verifyBucketNotification(notifications.get(0)); + verifyBucketNotification(notifications.get(1)); } @Test @@ -1714,7 +1716,7 @@ public void testDeleteNotification() { assertEquals(isDeleted, Boolean.TRUE); } - private void compareBucketsNotification(Notification value) { + private void verifyBucketNotification(Notification value) { assertNull(value.getGeneratedId()); assertEquals(CUSTOM_ATTRIBUTES, value.getCustomAttributes()); assertEquals(ETAG, value.getEtag()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index 74ba32b2a..8101def5c 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -74,6 +74,7 @@ import com.google.cloud.storage.HmacKey.HmacKeyState; import com.google.cloud.storage.HttpMethod; import com.google.cloud.storage.Notification; +import com.google.cloud.storage.NotificationInfo; import com.google.cloud.storage.PostPolicyV4; import com.google.cloud.storage.PostPolicyV4.PostFieldsV4; import com.google.cloud.storage.Rpo; @@ -167,7 +168,6 @@ public class ITStorageTest { private static RemoteStorageHelper remoteStorageHelper; private static Storage storage; - private static Notification notification; private static TopicAdminClient topicAdminClient; private static String kmsKeyOneResourcePath; private static String kmsKeyTwoResourcePath; @@ -229,7 +229,7 @@ public class ITStorageTest { private static final String PROJECT = ServiceOptions.getDefaultProjectId(); private static final String ID = UUID.randomUUID().toString().substring(0, 8); private static final String TOPIC = - String.format("projects/%s/topics/test_topic_foo_%s", PROJECT, ID); + String.format("projects/%s/topics/test_topic_foo_%s", PROJECT, ID).trim(); private static final Notification.PayloadFormat PAYLOAD_FORMAT = Notification.PayloadFormat.JSON_API_V1.JSON_API_V1; private static final Map CUSTOM_ATTRIBUTES = ImmutableMap.of("label1", "value1"); @@ -278,7 +278,7 @@ private static void unsetRequesterPays() { public static void afterClass() throws ExecutionException, InterruptedException { if (storage != null) { - /* Deletes the pubsub topic */ + /* Delete the Pub/Sub topic */ if (topicAdminClient != null) { topicAdminClient.deleteTopic(TOPIC); topicAdminClient.close(); @@ -3831,15 +3831,15 @@ public void testBucketUpdateTime() throws ExecutionException, InterruptedExcepti @Test public void testNotification() throws InterruptedException, ExecutionException { String bucketName = RemoteStorageHelper.generateBucketName(); - Bucket bucket = storage.create(BucketInfo.newBuilder(bucketName).setLocation("us").build()); - Notification bucketNotification = - Notification.newBuilder(TOPIC) + storage.create(BucketInfo.newBuilder(bucketName).setLocation("us").build()); + NotificationInfo notificationInfo = + NotificationInfo.newBuilder(TOPIC) .setCustomAttributes(CUSTOM_ATTRIBUTES) .setPayloadFormat(PAYLOAD_FORMAT) .build(); try { assertThat(storage.listNotifications(bucketName)).isEmpty(); - Notification notification = storage.addNotification(bucketName, bucketNotification); + Notification notification = storage.addNotification(bucketName, notificationInfo); assertThat(notification.getGeneratedId()).isNotNull(); assertThat(CUSTOM_ATTRIBUTES).isEqualTo(notification.getCustomAttributes()); assertThat(PAYLOAD_FORMAT.name()).isEqualTo(notification.getPayloadFormat().name()); @@ -3848,7 +3848,14 @@ public void testNotification() throws InterruptedException, ExecutionException { // Gets the notification with the specified id. Notification actualNotification = storage.getNotification(bucketName, notification.getGeneratedId()); - assertEquals(notification, actualNotification); + assertThat(actualNotification.getGeneratedId()).isEqualTo(notification.getGeneratedId()); + assertThat(actualNotification.getTopic().trim()).isEqualTo(notification.getTopic().trim()); + assertThat(actualNotification.getEtag()).isEqualTo(notification.getEtag()); + assertThat(actualNotification.getEventTypes()).isEqualTo(notification.getEventTypes()); + assertThat(actualNotification.getPayloadFormat()).isEqualTo(notification.getPayloadFormat()); + assertThat(actualNotification.getSelfLink()).isEqualTo(notification.getSelfLink()); + assertThat(actualNotification.getCustomAttributes()) + .isEqualTo(notification.getCustomAttributes()); // Retrieves the list of notifications associated with the bucket. List notifications = storage.listNotifications(bucketName); From 7cbda36cc6053c4ef21966f9a68064fa78b29610 Mon Sep 17 00:00:00 2001 From: athakor Date: Mon, 27 Jul 2020 17:50:17 +0530 Subject: [PATCH 15/18] feat: addressed the nits --- .../clirr-ignored-differences.xml | 2 +- .../google/cloud/storage/Notification.java | 4 ++-- .../cloud/storage/NotificationInfo.java | 24 +++++++++---------- .../com/google/cloud/storage/Storage.java | 10 ++++---- .../com/google/cloud/storage/StorageImpl.java | 2 +- .../cloud/storage/NotificationInfoTest.java | 6 ++--- .../cloud/storage/NotificationTest.java | 2 +- .../cloud/storage/StorageImplMockitoTest.java | 4 ++-- .../cloud/storage/it/ITStorageTest.java | 20 +++++++++------- 9 files changed, 38 insertions(+), 36 deletions(-) diff --git a/google-cloud-storage/clirr-ignored-differences.xml b/google-cloud-storage/clirr-ignored-differences.xml index f387cdfe9..8374be3fc 100644 --- a/google-cloud-storage/clirr-ignored-differences.xml +++ b/google-cloud-storage/clirr-ignored-differences.xml @@ -13,7 +13,7 @@ com/google/cloud/storage/Storage - *.Notification addNotification(*.String, *.NotificationInfo) + *.Notification createNotification(*.String, *.NotificationInfo) 7012 diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java index 2a62137b9..7f9107a58 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Notification.java @@ -41,8 +41,8 @@ public static class Builder extends NotificationInfo.Builder { } @Override - Builder setGeneratedId(String generatedId) { - infoBuilder.setGeneratedId(generatedId); + Builder setNotificationId(String notificationId) { + infoBuilder.setNotificationId(notificationId); return this; } diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java index ff0528661..df986ce2e 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/NotificationInfo.java @@ -65,7 +65,7 @@ public enum EventType { OBJECT_ARCHIVE } - private final String generatedId; + private final String notificationId; private final String topic; private final List eventTypes; private final Map customAttributes; @@ -78,7 +78,7 @@ public enum EventType { public abstract static class Builder { Builder() {} - abstract Builder setGeneratedId(String generatedId); + abstract Builder setNotificationId(String notificationId); public abstract Builder setSelfLink(String selfLink); @@ -101,7 +101,7 @@ public abstract static class Builder { /** Builder for {@code NotificationInfo}. */ public static class BuilderImpl extends Builder { - private String generatedId; + private String notificationId; private String topic; private List eventTypes; private Map customAttributes; @@ -115,7 +115,7 @@ public static class BuilderImpl extends Builder { } BuilderImpl(NotificationInfo notificationInfo) { - generatedId = notificationInfo.generatedId; + notificationId = notificationInfo.notificationId; etag = notificationInfo.etag; selfLink = notificationInfo.selfLink; topic = notificationInfo.topic; @@ -126,8 +126,8 @@ public static class BuilderImpl extends Builder { } @Override - Builder setGeneratedId(String generatedId) { - this.generatedId = generatedId; + Builder setNotificationId(String notificationId) { + this.notificationId = notificationId; return this; } @@ -183,7 +183,7 @@ public NotificationInfo build() { } NotificationInfo(BuilderImpl builder) { - generatedId = builder.generatedId; + notificationId = builder.notificationId; etag = builder.etag; selfLink = builder.selfLink; topic = builder.topic; @@ -194,8 +194,8 @@ public NotificationInfo build() { } /** Returns the service-generated id for the notification. */ - public String getGeneratedId() { - return generatedId; + public String getNotificationId() { + return notificationId; } /** Returns the topic in Pub/Sub that receives notifications. */ @@ -265,8 +265,8 @@ public String toString() { com.google.api.services.storage.model.Notification toPb() { com.google.api.services.storage.model.Notification notificationPb = new com.google.api.services.storage.model.Notification(); - if (generatedId != null) { - notificationPb.setId(generatedId); + if (notificationId != null) { + notificationPb.setId(notificationId); } notificationPb.setEtag(etag); if (customAttributes != null) { @@ -328,7 +328,7 @@ static NotificationInfo fromPb( com.google.api.services.storage.model.Notification notificationPb) { NotificationInfo.Builder builder = new NotificationInfo.BuilderImpl(notificationPb.getTopic()); if (notificationPb.getId() != null) { - builder.setGeneratedId(notificationPb.getId()); + builder.setNotificationId(notificationPb.getId()); } if (notificationPb.getEtag() != null) { builder.setEtag(notificationPb.getEtag()); diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index df03eccfb..634155f24 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -3627,9 +3627,9 @@ List testIamPermissions( ServiceAccount getServiceAccount(String projectId); /** - * Adds a new notification to the bucket. + * Creates the notification for a given bucket. * - *

Example of adding a notification: + *

Example of creating a notification: * *

{@code
    * String bucketName = "my-unique-bucket";
@@ -3637,9 +3637,9 @@ List testIamPermissions(
    * NotificationInfo notificationInfo = NotificationInfo.newBuilder(topic)
    *  .setCustomAttributes(ImmutableMap.of("label1", "value1"))
    *  .setEventTypes(NotificationInfo.EventType.OBJECT_FINALIZE)
-   *  .setPayloadFormat(Notification.PayloadFormat.JSON_API_V1)
+   *  .setPayloadFormat(NotificationInfo.PayloadFormat.JSON_API_V1)
    *  .build();
-   * Notification notification = storage.addNotification(bucketName, notificationInfo);
+   * Notification notification = storage.createNotification(bucketName, notificationInfo);
    * }
* * @param bucket name of the bucket @@ -3647,7 +3647,7 @@ List testIamPermissions( * @return the created notification * @throws StorageException upon failure */ - Notification addNotification(String bucket, NotificationInfo notificationInfo); + Notification createNotification(String bucket, NotificationInfo notificationInfo); /** * Gets the notification with the specified id. diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index a1315877f..3d0f9bafe 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -1375,7 +1375,7 @@ private U run(ResultRetryAlgorithm algorithm, Callable c, Function< } @Override - public Notification addNotification( + public Notification createNotification( final String bucket, final NotificationInfo notificationInfo) { final com.google.api.services.storage.model.Notification notificationPb = notificationInfo.toPb(); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java index 0b889b69d..fd50120a3 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationInfoTest.java @@ -66,7 +66,7 @@ public void testToBuilderIncomplete() { public void testOf() { NotificationInfo notificationInfo = NotificationInfo.of(TOPIC); assertEquals(TOPIC, notificationInfo.getTopic()); - assertNull(notificationInfo.getGeneratedId()); + assertNull(notificationInfo.getNotificationId()); assertNull(notificationInfo.getCustomAttributes()); assertNull(notificationInfo.getEtag()); assertNull(notificationInfo.getSelfLink()); @@ -78,7 +78,7 @@ public void testOf() { @Test public void testBuilder() { assertEquals(ETAG, NOTIFICATION_INFO.getEtag()); - assertNull(NOTIFICATION_INFO.getGeneratedId()); + assertNull(NOTIFICATION_INFO.getNotificationId()); assertEquals(SELF_LINK, NOTIFICATION_INFO.getSelfLink()); assertEquals(OBJECT_NAME_PREFIX, NOTIFICATION_INFO.getObjectNamePrefix()); assertEquals(PAYLOAD_FORMAT, NOTIFICATION_INFO.getPayloadFormat()); @@ -98,7 +98,7 @@ public void testToPbAndFromPb() { private void compareBucketsNotification(NotificationInfo expected, NotificationInfo actual) { assertEquals(expected, actual); - assertEquals(expected.getGeneratedId(), actual.getGeneratedId()); + assertEquals(expected.getNotificationId(), actual.getNotificationId()); assertEquals(expected.getCustomAttributes(), actual.getCustomAttributes()); assertEquals(expected.getEtag(), actual.getEtag()); assertEquals(expected.getSelfLink(), actual.getSelfLink()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java index 2c89a5157..2f1f7eb3c 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/NotificationTest.java @@ -112,7 +112,7 @@ public void testFromPb() { } private void compareBucketNotification(NotificationInfo expected, NotificationInfo actual) { - assertEquals(expected.getGeneratedId(), actual.getGeneratedId()); + assertEquals(expected.getNotificationId(), actual.getNotificationId()); assertEquals(expected.getCustomAttributes(), actual.getCustomAttributes()); assertEquals(expected.getEtag(), actual.getEtag()); assertEquals(expected.getSelfLink(), actual.getSelfLink()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java index 72b8a9b49..e601bd205 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java @@ -1682,7 +1682,7 @@ public void testAddNotification() { .when(storageRpcMock) .createNotification(BUCKET_NAME1, NOTIFICATION_INFO_01.toPb()); initializeService(); - Notification notification = storage.addNotification(BUCKET_NAME1, NOTIFICATION_INFO_01); + Notification notification = storage.createNotification(BUCKET_NAME1, NOTIFICATION_INFO_01); verifyBucketNotification(notification); } @@ -1717,7 +1717,7 @@ public void testDeleteNotification() { } private void verifyBucketNotification(Notification value) { - assertNull(value.getGeneratedId()); + assertNull(value.getNotificationId()); assertEquals(CUSTOM_ATTRIBUTES, value.getCustomAttributes()); assertEquals(ETAG, value.getEtag()); assertEquals(SELF_LINK, value.getSelfLink()); diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index 8101def5c..80d1ebc38 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -3839,16 +3839,17 @@ public void testNotification() throws InterruptedException, ExecutionException { .build(); try { assertThat(storage.listNotifications(bucketName)).isEmpty(); - Notification notification = storage.addNotification(bucketName, notificationInfo); - assertThat(notification.getGeneratedId()).isNotNull(); + Notification notification = storage.createNotification(bucketName, notificationInfo); + assertThat(notification.getNotificationId()).isNotNull(); assertThat(CUSTOM_ATTRIBUTES).isEqualTo(notification.getCustomAttributes()); assertThat(PAYLOAD_FORMAT.name()).isEqualTo(notification.getPayloadFormat().name()); assertThat(notification.getTopic().contains(TOPIC)).isTrue(); // Gets the notification with the specified id. Notification actualNotification = - storage.getNotification(bucketName, notification.getGeneratedId()); - assertThat(actualNotification.getGeneratedId()).isEqualTo(notification.getGeneratedId()); + storage.getNotification(bucketName, notification.getNotificationId()); + assertThat(actualNotification.getNotificationId()) + .isEqualTo(notification.getNotificationId()); assertThat(actualNotification.getTopic().trim()).isEqualTo(notification.getTopic().trim()); assertThat(actualNotification.getEtag()).isEqualTo(notification.getEtag()); assertThat(actualNotification.getEventTypes()).isEqualTo(notification.getEventTypes()); @@ -3860,13 +3861,14 @@ public void testNotification() throws InterruptedException, ExecutionException { // Retrieves the list of notifications associated with the bucket. List notifications = storage.listNotifications(bucketName); assertThat(notifications.size()).isEqualTo(1); - assertThat(notifications.get(0).getGeneratedId()) - .isEqualTo(actualNotification.getGeneratedId()); + assertThat(notifications.get(0).getNotificationId()) + .isEqualTo(actualNotification.getNotificationId()); // Deletes the notification with the specified id. - assertThat(storage.deleteNotification(bucketName, notification.getGeneratedId())).isTrue(); - assertThat(storage.deleteNotification(bucketName, notification.getGeneratedId())).isFalse(); - assertThat(storage.getNotification(bucketName, notification.getGeneratedId())).isNull(); + assertThat(storage.deleteNotification(bucketName, notification.getNotificationId())).isTrue(); + assertThat(storage.deleteNotification(bucketName, notification.getNotificationId())) + .isFalse(); + assertThat(storage.getNotification(bucketName, notification.getNotificationId())).isNull(); assertThat(storage.listNotifications(bucketName)).isEmpty(); } finally { RemoteStorageHelper.forceDelete(storage, bucketName, 5, TimeUnit.SECONDS); From 50e77a8e74dd37bf14fe791318f50793addf49cc Mon Sep 17 00:00:00 2001 From: athakor Date: Mon, 27 Jul 2020 18:09:27 +0530 Subject: [PATCH 16/18] feat: update test method name --- .../java/com/google/cloud/storage/StorageImplMockitoTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java index e601bd205..e69e3fe09 100644 --- a/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java +++ b/google-cloud-storage/src/test/java/com/google/cloud/storage/StorageImplMockitoTest.java @@ -1677,7 +1677,7 @@ public void testWriterFailure() { } @Test - public void testAddNotification() { + public void testCreateNotification() { doReturn(NOTIFICATION_INFO_01.toPb()) .when(storageRpcMock) .createNotification(BUCKET_NAME1, NOTIFICATION_INFO_01.toPb()); From ea6fc357c0faf053e3ebd707e97f5a9f84a0b410 Mon Sep 17 00:00:00 2001 From: Sydney Munro Date: Fri, 18 Mar 2022 16:31:37 -0700 Subject: [PATCH 17/18] Fix StorageImpl --- .../src/main/java/com/google/cloud/storage/StorageImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index 3d0f9bafe..9157bf9f9 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -16,6 +16,7 @@ package com.google.cloud.storage; +import static com.google.cloud.RetryHelper.runWithRetries; import static com.google.cloud.storage.PolicyHelper.convertToApiPolicy; import static com.google.cloud.storage.SignedUrlEncodingHelper.Rfc3986UriEncode; import static com.google.cloud.storage.spi.v1.StorageRpc.Option.DELIMITER; @@ -44,6 +45,7 @@ import com.google.cloud.PageImpl.NextPageFetcher; import com.google.cloud.Policy; import com.google.cloud.ReadChannel; +import com.google.cloud.RetryHelper.RetryHelperException; import com.google.cloud.Tuple; import com.google.cloud.WriteChannel; import com.google.cloud.storage.Acl.Entity; @@ -1435,7 +1437,7 @@ public List call() { ? ImmutableList.of() : Lists.transform( answer, - new Function() { + new com.google.common.base.Function() { @Override public Notification apply( com.google.api.services.storage.model.Notification notificationPb) { From 9d975766c665e9b4ec088a39bd59d6a9b145f3a5 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Fri, 18 Mar 2022 23:38:56 +0000 Subject: [PATCH 18/18] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- .../src/main/java/com/google/cloud/storage/StorageImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index 9157bf9f9..874d997eb 100644 --- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -1437,7 +1437,8 @@ public List call() { ? ImmutableList.of() : Lists.transform( answer, - new com.google.common.base.Function() { + new com.google.common.base.Function< + com.google.api.services.storage.model.Notification, Notification>() { @Override public Notification apply( com.google.api.services.storage.model.Notification notificationPb) {