diff options
author | Fabrice Bellingard <fabrice.bellingard@sonarsource.com> | 2013-01-30 15:08:34 +0100 |
---|---|---|
committer | Fabrice Bellingard <fabrice.bellingard@sonarsource.com> | 2013-01-30 15:23:22 +0100 |
commit | c91f6e066a0d4917b2cbace325db9ac6a12c2913 (patch) | |
tree | ca2fc6dc23954c5a561ddbe9115dc75aec10a7bf | |
parent | 8f9dacd45c67012dae0dc06df4f2baa483164bc6 (diff) | |
download | sonarqube-c91f6e066a0d4917b2cbace325db9ac6a12c2913.tar.gz sonarqube-c91f6e066a0d4917b2cbace325db9ac6a12c2913.zip |
SONAR-3959 Add NotificationDispatcherMetadata class
12 files changed, 342 insertions, 24 deletions
diff --git a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java index 16c3d9bf00a..d62857fbca8 100644 --- a/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java +++ b/plugins/sonar-email-notifications-plugin/src/main/java/org/sonar/plugins/emailnotifications/EmailNotificationsPlugin.java @@ -20,8 +20,8 @@ package org.sonar.plugins.emailnotifications; import com.google.common.collect.ImmutableList; -import org.sonar.api.ServerExtension; import org.sonar.api.SonarPlugin; +import org.sonar.api.notifications.NotificationDispatcherMetadata; import org.sonar.plugins.emailnotifications.alerts.AlertsEmailTemplate; import org.sonar.plugins.emailnotifications.alerts.AlertsOnMyFavouriteProject; import org.sonar.plugins.emailnotifications.newviolations.NewViolationsEmailTemplate; @@ -32,18 +32,28 @@ import org.sonar.plugins.emailnotifications.reviews.ReviewEmailTemplate; import java.util.List; public class EmailNotificationsPlugin extends SonarPlugin { - public List<Class<? extends ServerExtension>> getExtensions() { + public List<?> getExtensions() { return ImmutableList.of( EmailNotificationChannel.class, + // Notify incoming violations on my favourite projects NewViolationsOnMyFavouriteProject.class, + NotificationDispatcherMetadata.create("NewViolationsOnMyFavouriteProject") + .setProperty(NotificationDispatcherMetadata.GLOBAL_NOTIFICATION, "true"), NewViolationsEmailTemplate.class, + // Notify reviews changes ChangesInReviewAssignedToMeOrCreatedByMe.class, + NotificationDispatcherMetadata.create("ChangesInReviewAssignedToMeOrCreatedByMe") + .setProperty(NotificationDispatcherMetadata.GLOBAL_NOTIFICATION, "true"), ReviewEmailTemplate.class, + // Notify alerts on my favourite projects AlertsOnMyFavouriteProject.class, + NotificationDispatcherMetadata.create("AlertsOnMyFavouriteProject") + .setProperty(NotificationDispatcherMetadata.GLOBAL_NOTIFICATION, "true"), AlertsEmailTemplate.class - ); + + ); } } diff --git a/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationsPluginTest.java b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationsPluginTest.java index aeb4755d940..55096f5565b 100644 --- a/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationsPluginTest.java +++ b/plugins/sonar-email-notifications-plugin/src/test/java/org/sonar/plugins/emailnotifications/EmailNotificationsPluginTest.java @@ -26,6 +26,6 @@ import static org.fest.assertions.Assertions.assertThat; public class EmailNotificationsPluginTest { @Test public void should_get_extensions() { - assertThat(new EmailNotificationsPlugin().getExtensions()).hasSize(7); + assertThat(new EmailNotificationsPlugin().getExtensions()).hasSize(10); } } diff --git a/sonar-core/src/main/java/org/sonar/core/notification/DefaultNotificationManager.java b/sonar-core/src/main/java/org/sonar/core/notification/DefaultNotificationManager.java index 49a276f2614..ce69b5a7006 100644 --- a/sonar-core/src/main/java/org/sonar/core/notification/DefaultNotificationManager.java +++ b/sonar-core/src/main/java/org/sonar/core/notification/DefaultNotificationManager.java @@ -19,6 +19,7 @@ */ package org.sonar.core.notification; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.SetMultimap; @@ -60,13 +61,6 @@ public class DefaultNotificationManager implements NotificationManager { } /** - * Returns all the available notification channels - */ - public List<NotificationChannel> getChannels() { - return Arrays.asList(notificationChannels); - } - - /** * {@inheritDoc} */ public void scheduleForSending(Notification notification) { @@ -122,6 +116,11 @@ public class DefaultNotificationManager implements NotificationManager { return recipients; } + @VisibleForTesting + protected List<NotificationChannel> getChannels() { + return Arrays.asList(notificationChannels); + } + private void addUsersToRecipientListForChannel(List<String> users, SetMultimap<String, NotificationChannel> recipients, NotificationChannel channel) { for (String username : users) { recipients.put(username, channel); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/notifications/NotificationDispatcherMetadata.java b/sonar-plugin-api/src/main/java/org/sonar/api/notifications/NotificationDispatcherMetadata.java new file mode 100644 index 00000000000..a5dafc6e4d2 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/notifications/NotificationDispatcherMetadata.java @@ -0,0 +1,81 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.notifications; + +import com.google.common.collect.Maps; +import org.sonar.api.ServerExtension; +import org.sonar.api.SonarPlugin; + +import java.util.Map; + +/** + * <p> + * Notification dispatchers (see {@link NotificationDispatcher}) can define their own metadata class in order + * to tell more about them. + * <br/> + * Instances of those classes must be passed to Pico container (generally in the + * {@link SonarPlugin#getExtensions()} method implementation). + * </p> + * + * @since 3.5 + */ +public final class NotificationDispatcherMetadata implements ServerExtension { + + public static final String GLOBAL_NOTIFICATION = "globalNotification"; + public static final String PER_PROJECT_NOTIFICATION = "perProjectNotification"; + + private String dispatcherKey; + private Map<String, String> properties; + + private NotificationDispatcherMetadata(String dispatcherKey) { + this.dispatcherKey = dispatcherKey; + this.properties = Maps.newHashMap(); + } + + /** + * Creates a new metadata instance for the given dispatcher. + */ + public static NotificationDispatcherMetadata create(String dispatcherKey) { + return new NotificationDispatcherMetadata(dispatcherKey); + } + + /** + * Sets a property on this metadata object. + */ + public NotificationDispatcherMetadata setProperty(String key, String value) { + properties.put(key, value); + return this; + } + + /** + * Gives the property for the given key. + */ + public String getProperty(String key) { + return properties.get(key); + } + + /** + * Returns the unique key of the dispatcher. + */ + public String getDispatcherKey() { + return dispatcherKey; + } + +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/notifications/NotificationDispatcherMetadataTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/notifications/NotificationDispatcherMetadataTest.java new file mode 100644 index 00000000000..b585a0f6cef --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/notifications/NotificationDispatcherMetadataTest.java @@ -0,0 +1,46 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.notifications; + +import org.junit.Before; +import org.junit.Test; + +import static org.fest.assertions.Assertions.assertThat; + +public class NotificationDispatcherMetadataTest { + + private NotificationDispatcherMetadata metadata; + + @Before + public void init() { + metadata = NotificationDispatcherMetadata.create("NewViolations").setProperty("global", "true"); + } + + @Test + public void shouldReturnDispatcherKey() { + assertThat(metadata.getDispatcherKey()).isEqualTo("NewViolations"); + } + + @Test + public void shouldReturnProperty() { + assertThat(metadata.getProperty("global")).isEqualTo("true"); + assertThat(metadata.getProperty("per-project")).isNull(); + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/notifications/NotificationCenter.java b/sonar-server/src/main/java/org/sonar/server/notifications/NotificationCenter.java new file mode 100644 index 00000000000..620a4e285f7 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/notifications/NotificationCenter.java @@ -0,0 +1,103 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.server.notifications; + +import com.google.common.collect.Lists; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.ServerComponent; +import org.sonar.api.notifications.NotificationChannel; +import org.sonar.api.notifications.NotificationDispatcherMetadata; + +import javax.annotation.Nullable; + +import java.util.Arrays; +import java.util.List; + +/** + * @since 3.5 + */ +public class NotificationCenter implements ServerComponent { + + private static final Logger LOG = LoggerFactory.getLogger(NotificationCenter.class); + + private final NotificationDispatcherMetadata[] dispatchersMetadata; + private final NotificationChannel[] channels; + + /** + * Constructor for {@link NotificationCenter} + */ + public NotificationCenter(NotificationDispatcherMetadata[] metadata, NotificationChannel[] channels) { + this.dispatchersMetadata = metadata; + this.channels = channels; + LOG.info("====================> " + metadata.length); + LOG.info("====================> " + channels.length); + } + + /** + * Default constructor when no channels. + */ + public NotificationCenter(NotificationDispatcherMetadata[] metadata) { + this(metadata, new NotificationChannel[0]); + LOG.warn("There is no notification channel - no notification will be delivered!"); + } + + /** + * Default constructor when no dispatcher metadata. + */ + public NotificationCenter(NotificationChannel[] channels) { + this(new NotificationDispatcherMetadata[0], channels); + } + + /** + * Default constructor. + */ + public NotificationCenter() { + this(new NotificationDispatcherMetadata[0], new NotificationChannel[0]); + LOG.warn("There is no notification channel - no notification will be delivered!"); + } + + /** + * Returns all the available channels. + */ + public List<NotificationChannel> getChannels() { + return Arrays.asList(channels); + } + + /** + * Returns all the available dispatchers which metadata matches the given property and its value. + * <br/> + * If "propertyValue" is null, the verification is done on the existence of such a property (whatever the value). + */ + public List<String> getDispatcherKeysForProperty(String propertyKey, @Nullable String propertyValue) { + List<String> keys = Lists.newArrayList(); + for (NotificationDispatcherMetadata metadata : dispatchersMetadata) { + String dispatcherKey = metadata.getDispatcherKey(); + String value = metadata.getProperty(propertyKey); + if (value != null) { + if (propertyValue == null || value.equals(propertyValue)) { + keys.add(dispatcherKey); + } + } + } + return keys; + } + +} diff --git a/sonar-server/src/main/java/org/sonar/server/notifications/NotificationService.java b/sonar-server/src/main/java/org/sonar/server/notifications/NotificationService.java index 49b4e8237c0..c52906d3523 100644 --- a/sonar-server/src/main/java/org/sonar/server/notifications/NotificationService.java +++ b/sonar-server/src/main/java/org/sonar/server/notifications/NotificationService.java @@ -164,12 +164,9 @@ public class NotificationService implements ServerComponent { } } - public List<NotificationDispatcher> getDispatchers() { + @VisibleForTesting + protected List<NotificationDispatcher> getDispatchers() { return Arrays.asList(dispatchers); } - public List<NotificationChannel> getChannels() { - return manager.getChannels(); - } - } diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 964382f6682..ae490bf7224 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -73,6 +73,7 @@ import org.sonar.server.charts.ChartFactory; import org.sonar.server.configuration.Backup; import org.sonar.server.configuration.ProfilesManager; import org.sonar.server.database.EmbeddedDatabaseFactory; +import org.sonar.server.notifications.NotificationCenter; import org.sonar.server.notifications.NotificationService; import org.sonar.server.notifications.reviews.ReviewsNotificationManager; import org.sonar.server.plugins.ApplicationDeployer; @@ -257,6 +258,7 @@ public final class Platform { // Notifications servicesContainer.addSingleton(EmailSettings.class); servicesContainer.addSingleton(NotificationService.class); + servicesContainer.addSingleton(NotificationCenter.class); servicesContainer.addSingleton(DefaultNotificationManager.class); servicesContainer.addSingleton(ReviewsNotificationManager.class); diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/account_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/account_controller.rb index beac85292fb..875aa77cccc 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/account_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/account_controller.rb @@ -22,9 +22,9 @@ class AccountController < ApplicationController before_filter :login_required def index - notification_service = java_facade.getCoreComponentByClassname('org.sonar.server.notifications.NotificationService') + notification_service = java_facade.getCoreComponentByClassname('org.sonar.server.notifications.NotificationCenter') @channels = notification_service.getChannels() - @dispatchers = notification_service.getDispatchers() + @dispatchers = notification_service.getDispatcherKeysForProperty("globalNotification", "true") @notifications = {} for property in Property.find(:all, :conditions => ['prop_key like ? AND user_id = ?', 'notification.%', current_user.id]) @notifications[property.key.sub('notification.', '')] = true diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb index aaabf828d4d..c6285fe64b6 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/account/index.html.erb @@ -68,11 +68,11 @@ </tr> <% for dispatcher in @dispatchers %> <tr> - <td><%= message('notification.dispatcher.' + dispatcher.getKey()) -%></td> + <td><%= message('notification.dispatcher.' + dispatcher) -%></td> <td> <% for channel in @channels - notification_id = dispatcher.getKey() + '.' + channel.getKey() + notification_id = dispatcher + '.' + channel.getKey() check_box_id = 'notifications[' + notification_id + ']' check_box_checked = @notifications[notification_id] %> diff --git a/sonar-server/src/test/java/org/sonar/server/notifications/NotificationCenterTest.java b/sonar-server/src/test/java/org/sonar/server/notifications/NotificationCenterTest.java new file mode 100644 index 00000000000..8eeb725bf1e --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/notifications/NotificationCenterTest.java @@ -0,0 +1,83 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.server.notifications; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.sonar.api.notifications.NotificationChannel; +import org.sonar.api.notifications.NotificationDispatcherMetadata; + +import static org.fest.assertions.Assertions.assertThat; + +public class NotificationCenterTest { + + @Mock + private NotificationChannel emailChannel; + + @Mock + private NotificationChannel gtalkChannel; + + private NotificationCenter notificationCenter; + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + + NotificationDispatcherMetadata metadata1 = NotificationDispatcherMetadata.create("Dispatcher1").setProperty("global", "true").setProperty("on-project", "true"); + NotificationDispatcherMetadata metadata2 = NotificationDispatcherMetadata.create("Dispatcher2").setProperty("global", "true"); + NotificationDispatcherMetadata metadata3 = NotificationDispatcherMetadata.create("Dispatcher3").setProperty("global", "FOO").setProperty("on-project", "BAR"); + + notificationCenter = new NotificationCenter( + new NotificationDispatcherMetadata[] {metadata1, metadata2, metadata3}, + new NotificationChannel[] {emailChannel, gtalkChannel} + ); + } + + @Test + public void shouldReturnChannels() { + assertThat(notificationCenter.getChannels()).containsOnly(emailChannel, gtalkChannel); + } + + @Test + public void shouldReturnDispatcherKeysForSpecificPropertyValue() { + assertThat(notificationCenter.getDispatcherKeysForProperty("global", "true")).containsOnly("Dispatcher1", "Dispatcher2"); + } + + @Test + public void shouldReturnDispatcherKeysForExistenceOfProperty() { + assertThat(notificationCenter.getDispatcherKeysForProperty("on-project", null)).containsOnly("Dispatcher1", "Dispatcher3"); + } + + @Test + public void testDefaultConstructors() { + notificationCenter = new NotificationCenter(new NotificationChannel[] {emailChannel}); + assertThat(notificationCenter.getChannels()).hasSize(1); + + notificationCenter = new NotificationCenter(); + assertThat(notificationCenter.getChannels()).hasSize(0); + + notificationCenter = new NotificationCenter(new NotificationDispatcherMetadata[] {NotificationDispatcherMetadata.create("Dispatcher1").setProperty("global", "true")}); + assertThat(notificationCenter.getChannels()).hasSize(0); + assertThat(notificationCenter.getDispatcherKeysForProperty("global", null)).hasSize(1); + } + +} diff --git a/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceTest.java b/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceTest.java index d2eeb8cce86..21e4a956282 100644 --- a/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.notifications; -import com.google.common.collect.Lists; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -63,7 +62,6 @@ public class NotificationServiceTest { when(commentOnReviewCreatedByMe.getKey()).thenReturn("comment on review created by me"); when(queueElement.getNotification()).thenReturn(notification); when(manager.getFromQueue()).thenReturn(queueElement).thenReturn(null); - when(manager.getChannels()).thenReturn(Lists.newArrayList(emailChannel, gtalkChannel)); Settings settings = new Settings().setProperty("sonar.notifications.delay", 1L); @@ -179,10 +177,9 @@ public class NotificationServiceTest { } @Test - public void shouldReturnDispatcherAndChannelListsUsedInWebapp() { + public void shouldReturnDispatcherList() { setUpMocks(CREATOR_SIMON, ASSIGNEE_SIMON); - assertThat(service.getChannels()).containsOnly(emailChannel, gtalkChannel); assertThat(service.getDispatchers()).containsOnly(commentOnReviewAssignedToMe, commentOnReviewCreatedByMe); } |