diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-06-08 15:22:34 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-06-08 15:22:34 +0200 |
commit | abbf32571232db81a5343db17a933a9ce6923b44 (patch) | |
tree | be13ec6d05a79259e5c71c7c3b0eab3003adbbe0 /server | |
parent | 81d37f61213eb6d51e1185da984e7390e459c7a4 (diff) | |
download | sonarqube-abbf32571232db81a5343db17a933a9ce6923b44.tar.gz sonarqube-abbf32571232db81a5343db17a933a9ce6923b44.zip |
SONAR-6567 move notifications from sonar-core to sonar-server
Diffstat (limited to 'server')
34 files changed, 898 insertions, 54 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/SendIssueNotificationsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/SendIssueNotificationsStep.java index cbc929306ea..5129e8a4959 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/SendIssueNotificationsStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/SendIssueNotificationsStep.java @@ -34,13 +34,13 @@ import org.sonar.server.issue.notification.MyNewIssuesNotification; import org.sonar.server.issue.notification.NewIssuesNotification; import org.sonar.server.issue.notification.NewIssuesNotificationFactory; import org.sonar.server.issue.notification.NewIssuesStatistics; -import org.sonar.server.notifications.NotificationService; +import org.sonar.server.notification.NotificationService; import org.sonar.server.util.CloseableIterator; /** * Reads issues from disk cache and send related notifications. For performance reasons, * the standard notification DB queue is not used as a temporary storage. Notifications - * are directly processed by {@link org.sonar.server.notifications.NotificationService}. + * are directly processed by {@link NotificationService}. */ public class SendIssueNotificationsStep implements ComputationStep { /** diff --git a/server/sonar-server/src/main/java/org/sonar/server/event/NewAlerts.java b/server/sonar-server/src/main/java/org/sonar/server/event/NewAlerts.java index cf4c219e848..6ec224ec1f6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/event/NewAlerts.java +++ b/server/sonar-server/src/main/java/org/sonar/server/event/NewAlerts.java @@ -24,9 +24,9 @@ import org.sonar.api.notifications.*; import java.util.Collection; import java.util.Map; -import org.sonar.core.notification.NotificationDispatcher; -import org.sonar.core.notification.NotificationDispatcherMetadata; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationDispatcher; +import org.sonar.server.notification.NotificationDispatcherMetadata; +import org.sonar.server.notification.NotificationManager; /** * This dispatcher means: "notify me each new alert event". diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java index 29f84cafcca..53c4539b16f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java @@ -44,7 +44,7 @@ import org.sonar.api.utils.log.Loggers; import org.sonar.core.component.ComponentDto; import org.sonar.core.issue.db.IssueDto; import org.sonar.core.issue.db.IssueStorage; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationManager; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; import org.sonar.server.db.DbClient; diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java index b407ec4b635..0f342ce585a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java @@ -26,7 +26,7 @@ import org.sonar.api.issue.ActionPlan; import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.issue.internal.IssueChangeContext; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationManager; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; import org.sonar.api.rules.Rule; diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/ChangesOnMyIssueNotificationDispatcher.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/ChangesOnMyIssueNotificationDispatcher.java index b38eb2f855b..5aa290eb83b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/ChangesOnMyIssueNotificationDispatcher.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/ChangesOnMyIssueNotificationDispatcher.java @@ -25,9 +25,9 @@ import org.sonar.api.notifications.*; import javax.annotation.Nullable; import java.util.Collection; -import org.sonar.core.notification.NotificationDispatcher; -import org.sonar.core.notification.NotificationDispatcherMetadata; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationDispatcher; +import org.sonar.server.notification.NotificationDispatcherMetadata; +import org.sonar.server.notification.NotificationManager; /** * This dispatcher means: "notify me when a change is done on an issue that is assigned to me or reported by me". diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/DoNotFixNotificationDispatcher.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/DoNotFixNotificationDispatcher.java index e4f0a5f81d9..1ee261ea214 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/DoNotFixNotificationDispatcher.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/DoNotFixNotificationDispatcher.java @@ -27,9 +27,9 @@ import org.sonar.api.notifications.*; import java.util.Collection; import java.util.Map; -import org.sonar.core.notification.NotificationDispatcher; -import org.sonar.core.notification.NotificationDispatcherMetadata; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationDispatcher; +import org.sonar.server.notification.NotificationDispatcherMetadata; +import org.sonar.server.notification.NotificationManager; /** * This dispatcher means: "notify me when an issue is resolved as false positive or won't fix". diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesNotificationDispatcher.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesNotificationDispatcher.java index 3810279554f..c4be5a62776 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesNotificationDispatcher.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/MyNewIssuesNotificationDispatcher.java @@ -24,9 +24,9 @@ import com.google.common.collect.Multimap; import org.sonar.api.notifications.*; import java.util.Collection; -import org.sonar.core.notification.NotificationDispatcher; -import org.sonar.core.notification.NotificationDispatcherMetadata; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationDispatcher; +import org.sonar.server.notification.NotificationDispatcherMetadata; +import org.sonar.server.notification.NotificationManager; /** * This dispatcher means: "notify me when new issues are introduced during project analysis" diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotificationDispatcher.java b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotificationDispatcher.java index e346b1af744..6c28a8aadf9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotificationDispatcher.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/notification/NewIssuesNotificationDispatcher.java @@ -24,9 +24,9 @@ import org.sonar.api.notifications.*; import java.util.Collection; import java.util.Map; -import org.sonar.core.notification.NotificationDispatcher; -import org.sonar.core.notification.NotificationDispatcherMetadata; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationDispatcher; +import org.sonar.server.notification.NotificationDispatcherMetadata; +import org.sonar.server.notification.NotificationManager; /** * This dispatcher means: "notify me when new issues are introduced during project analysis" diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/DefaultNotificationManager.java b/server/sonar-server/src/main/java/org/sonar/server/notification/DefaultNotificationManager.java new file mode 100644 index 00000000000..82706d1001d --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/DefaultNotificationManager.java @@ -0,0 +1,177 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.notification; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import com.google.common.collect.SetMultimap; +import java.io.IOException; +import java.io.InvalidClassException; +import java.util.Arrays; +import java.util.List; +import javax.annotation.Nullable; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationChannel; +import org.sonar.api.utils.SonarException; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.core.notification.db.NotificationQueueDao; +import org.sonar.core.notification.db.NotificationQueueDto; +import org.sonar.core.properties.PropertiesDao; + +public class DefaultNotificationManager implements NotificationManager { + + private static final Logger LOG = Loggers.get(DefaultNotificationManager.class); + + private static final String UNABLE_TO_READ_NOTIFICATION = "Unable to read notification"; + + private NotificationChannel[] notificationChannels; + private NotificationQueueDao notificationQueueDao; + private PropertiesDao propertiesDao; + + private boolean alreadyLoggedDeserializationIssue = false; + + /** + * Default constructor used by Pico + */ + public DefaultNotificationManager(NotificationChannel[] channels, NotificationQueueDao notificationQueueDao, PropertiesDao propertiesDao) { + this.notificationChannels = channels; + this.notificationQueueDao = notificationQueueDao; + this.propertiesDao = propertiesDao; + } + + /** + * Constructor if no notification channel + */ + public DefaultNotificationManager(NotificationQueueDao notificationQueueDao, PropertiesDao propertiesDao) { + this(new NotificationChannel[0], notificationQueueDao, propertiesDao); + } + + /** + * {@inheritDoc} + */ + @Override + public void scheduleForSending(Notification notification) { + NotificationQueueDto dto = NotificationQueueDto.toNotificationQueueDto(notification); + notificationQueueDao.insert(Arrays.asList(dto)); + } + + @Override + public void scheduleForSending(List<Notification> notification) { + notificationQueueDao.insert(Lists.transform(notification, new Function<Notification, NotificationQueueDto>() { + @Override + public NotificationQueueDto apply(Notification notification) { + return NotificationQueueDto.toNotificationQueueDto(notification); + } + })); + } + + /** + * Give the notification queue so that it can be processed + */ + public Notification getFromQueue() { + int batchSize = 1; + List<NotificationQueueDto> notificationDtos = notificationQueueDao.findOldest(batchSize); + if (notificationDtos.isEmpty()) { + return null; + } + notificationQueueDao.delete(notificationDtos); + + return convertToNotification(notificationDtos); + } + + private Notification convertToNotification(List<NotificationQueueDto> notifications) { + try { + // If batchSize is increased then we should return a list instead of a single element + return notifications.get(0).toNotification(); + } catch (InvalidClassException e) { + // SONAR-4739 + if (!alreadyLoggedDeserializationIssue) { + logDeserializationIssue(); + alreadyLoggedDeserializationIssue = true; + } + return null; + } catch (IOException e) { + throw new SonarException(UNABLE_TO_READ_NOTIFICATION, e); + + } catch (ClassNotFoundException e) { + throw new SonarException(UNABLE_TO_READ_NOTIFICATION, e); + } + } + + @VisibleForTesting + void logDeserializationIssue() { + LOG.warn("It is impossible to send pending notifications which existed prior to the upgrade of SonarQube. They will be ignored."); + } + + public long count() { + return notificationQueueDao.count(); + } + + /** + * {@inheritDoc} + */ + @Override + public Multimap<String, NotificationChannel> findSubscribedRecipientsForDispatcher(NotificationDispatcher dispatcher, @Nullable Integer resourceId) { + String dispatcherKey = dispatcher.getKey(); + + SetMultimap<String, NotificationChannel> recipients = HashMultimap.create(); + for (NotificationChannel channel : notificationChannels) { + String channelKey = channel.getKey(); + + // Find users subscribed globally to the dispatcher (i.e. not on a specific project) + addUsersToRecipientListForChannel(propertiesDao.findUsersForNotification(dispatcherKey, channelKey, null), recipients, channel); + + if (resourceId != null) { + // Find users subscribed to the dispatcher specifically for the resource + addUsersToRecipientListForChannel(propertiesDao.findUsersForNotification(dispatcherKey, channelKey, resourceId.longValue()), recipients, channel); + } + } + + return recipients; + } + + @Override + public Multimap<String, NotificationChannel> findNotificationSubscribers(NotificationDispatcher dispatcher, @Nullable String componentKey) { + String dispatcherKey = dispatcher.getKey(); + + SetMultimap<String, NotificationChannel> recipients = HashMultimap.create(); + for (NotificationChannel channel : notificationChannels) { + addUsersToRecipientListForChannel(propertiesDao.findNotificationSubscribers(dispatcherKey, channel.getKey(), componentKey), recipients, channel); + } + + return recipients; + } + + @VisibleForTesting + protected List<NotificationChannel> getChannels() { + return Arrays.asList(notificationChannels); + } + + private static void addUsersToRecipientListForChannel(List<String> users, SetMultimap<String, NotificationChannel> recipients, NotificationChannel channel) { + for (String username : users) { + recipients.put(username, channel); + } + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/notifications/NotificationCenter.java b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationCenter.java index cf43dca0c31..b739a60edcd 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notifications/NotificationCenter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationCenter.java @@ -17,12 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.notifications; +package org.sonar.server.notification; import com.google.common.collect.Lists; import org.sonar.api.server.ServerSide; import org.sonar.api.notifications.NotificationChannel; -import org.sonar.core.notification.NotificationDispatcherMetadata; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationDispatcher.java b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationDispatcher.java new file mode 100644 index 00000000000..3c99cbe0003 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationDispatcher.java @@ -0,0 +1,130 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.notification; + +import org.apache.commons.lang.StringUtils; +import org.sonar.api.ExtensionPoint; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationChannel; +import org.sonar.api.server.ServerSide; + +/** + * <p> + * Plugins should extend this class to provide logic to determine which users are interested in receiving notifications, + * along with which delivery channels they selected. + * </p> + * For example: + * <ul> + * <li>notify me by email when someone comments an issue reported by me</li> + * <li>notify me by twitter when someone comments an issue assigned to me</li> + * <li>notify me by Jabber when someone mentions me in an issue comment</li> + * <li>send me by SMS when there are system notifications (like password reset, account creation, ...)</li> + * </ul> + * + * @since 2.10 + */ +@ServerSide +@ExtensionPoint +public abstract class NotificationDispatcher { + + private final String notificationType; + + /** + * Additional information related to the notification, which will be used + * to know who should receive the notification. + */ + public interface Context { + /** + * This method is not used any longer. Calling it will result in an {@link UnsupportedOperationException}. + * + * @deprecated Use {@link #addUser(String, NotificationChannel)} instead. + */ + @Deprecated + void addUser(String userLogin); + + /** + * Adds a user that will be notified through the given notification channel. + * + * @param userLogin the user login + * @param notificationChannel the notification channel to use for this user + */ + void addUser(String userLogin, NotificationChannel notificationChannel); + } + + /** + * Creates a new dispatcher for notifications of the given type. + * + * @param notificationType the type of notifications handled by this dispatcher + */ + public NotificationDispatcher(String notificationType) { + this.notificationType = notificationType; + } + + /** + * Creates a new generic dispatcher, used for any kind of notification. + * <p/> + * Should be avoided and replaced by the other constructor - as it is easier to understand that a + * dispatcher listens for a specific type of notification. + */ + public NotificationDispatcher() { + this(""); + } + + /** + * The unique key of this dispatcher. By default it's the class name without the package prefix. + * <p/> + * The related label in l10n bundles is 'notification.dispatcher.<key>', for example 'notification.dispatcher.NewFalsePositive'. + */ + public String getKey() { + return getClass().getSimpleName(); + } + + /** + * @since 5.1 + */ + public String getType() { + return notificationType; + } + + /** + * <p> + * Performs the dispatch. + * </p> + */ + public final void performDispatch(Notification notification, Context context) { + if (StringUtils.equals(notification.getType(), notificationType) || StringUtils.equals("", notificationType)) { + dispatch(notification, context); + } + } + + /** + * <p> + * Implements the logic that defines which users will receive the notification. + * </p> + * The purpose of this method is to populate the context object with users, based on the type of notification and the content of the notification. + */ + public abstract void dispatch(Notification notification, Context context); + + @Override + public String toString() { + return getKey(); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationDispatcherMetadata.java b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationDispatcherMetadata.java new file mode 100644 index 00000000000..de80ec7a2a7 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationDispatcherMetadata.java @@ -0,0 +1,102 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.notification; + +import com.google.common.collect.Maps; +import java.util.Map; +import org.sonar.api.server.ServerSide; + +/** + * <p> + * Notification dispatchers (see {@link NotificationDispatcher}) can define their own metadata class in order + * to tell more about them. + * <p/> + * Instances of these classes must be declared in {@link org.sonar.api.SonarPlugin#getExtensions()}. + * + * @since 3.5 + */ +@ServerSide +public final class NotificationDispatcherMetadata { + + 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. + * <p/> + * By default the key is the class name without package. It can be changed by overriding + * {@link NotificationDispatcher#getKey()}. + */ + 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; + } + + @Override + public String toString() { + return dispatcherKey; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + NotificationDispatcherMetadata that = (NotificationDispatcherMetadata) o; + return dispatcherKey.equals(that.dispatcherKey); + } + + @Override + public int hashCode() { + return dispatcherKey.hashCode(); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationManager.java b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationManager.java new file mode 100644 index 00000000000..d499a8fcc5c --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationManager.java @@ -0,0 +1,70 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.notification; + +import com.google.common.collect.Multimap; +import java.util.List; +import javax.annotation.Nullable; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationChannel; + +/** + * <p> + * The notification manager receives notifications and is in charge of storing them so that they are processed by the notification service. + * </p> + * <p> + * Pico provides an instance of this class, and plugins just need to create notifications and pass them to this manager with + * the {@link NotificationManager#scheduleForSending(Notification)} method. + * </p> + */ +public interface NotificationManager { + + /** + * Receives a notification and stores it so that it is processed by the notification service. + * + * @param notification the notification. + */ + void scheduleForSending(Notification notification); + + /** + * Receives notifications and stores them so that they are processed by the notification service. + * + * @param notifications the notifications. + * @since 3.7.1 + */ + void scheduleForSending(List<Notification> notifications); + + /** + * <p> + * Returns the list of users who subscribed to the given dispatcher, along with the notification channels (email, twitter, ...) that they choose + * for this dispatcher. + * </p> + * <p> + * The resource ID can be null in case of notifications that have nothing to do with a specific project (like system notifications). + * </p> + * + * @param dispatcher the dispatcher for which this list of users is requested + * @param resourceId the optional resource which is concerned by this request + * @return the list of user login along with the subscribed channels + */ + Multimap<String, NotificationChannel> findSubscribedRecipientsForDispatcher(NotificationDispatcher dispatcher, @Nullable Integer resourceId); + + Multimap<String, NotificationChannel> findNotificationSubscribers(NotificationDispatcher dispatcher, @Nullable String componentKey); +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/notifications/NotificationService.java b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationService.java index e33af89334d..b3951e8ee02 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notifications/NotificationService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/NotificationService.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.notifications; +package org.sonar.server.notification; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.HashMultimap; @@ -38,10 +38,8 @@ import org.sonar.api.server.ServerSide; import org.sonar.api.config.Settings; import org.sonar.api.notifications.Notification; import org.sonar.api.notifications.NotificationChannel; -import org.sonar.core.notification.NotificationDispatcher; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; -import org.sonar.core.notification.DefaultNotificationManager; import org.sonar.jpa.session.DatabaseSessionFactory; import org.sonar.server.db.DbClient; diff --git a/server/sonar-server/src/main/java/org/sonar/server/notifications/email/AlertsEmailTemplate.java b/server/sonar-server/src/main/java/org/sonar/server/notification/email/AlertsEmailTemplate.java index 0ea9c3c5544..77a53501929 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notifications/email/AlertsEmailTemplate.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/email/AlertsEmailTemplate.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.notifications.email; +package org.sonar.server.notification.email; import org.apache.commons.lang.StringUtils; import org.sonar.api.config.EmailSettings; diff --git a/server/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailNotificationChannel.java b/server/sonar-server/src/main/java/org/sonar/server/notification/email/EmailNotificationChannel.java index 3b96270736b..de7dc0f81ea 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notifications/email/EmailNotificationChannel.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/email/EmailNotificationChannel.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.notifications.email; +package org.sonar.server.notification.email; import java.net.MalformedURLException; import java.net.URL; diff --git a/server/sonar-server/src/main/java/org/sonar/server/notifications/email/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/notification/email/package-info.java index a81d297b0c7..f583fa78310 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notifications/email/package-info.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/email/package-info.java @@ -18,6 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @ParametersAreNonnullByDefault -package org.sonar.server.notifications.email; +package org.sonar.server.notification.email; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/notifications/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/notification/package-info.java index 34262049a99..71e0748a18c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/notifications/package-info.java +++ b/server/sonar-server/src/main/java/org/sonar/server/notification/package-info.java @@ -19,6 +19,6 @@ */ @ParametersAreNonnullByDefault -package org.sonar.server.notifications; +package org.sonar.server.notification; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index ca0260e5dea..21f69f49d65 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -38,7 +38,7 @@ import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.workflow.FunctionExecutor; import org.sonar.core.issue.workflow.IssueWorkflow; import org.sonar.core.metric.DefaultMetricFinder; -import org.sonar.core.notification.DefaultNotificationManager; +import org.sonar.server.notification.DefaultNotificationManager; import org.sonar.core.permission.PermissionFacade; import org.sonar.core.qualitygate.db.ProjectQgateAssociationDao; import org.sonar.core.qualitygate.db.QualityGateConditionDao; @@ -171,10 +171,10 @@ import org.sonar.server.measure.ws.ManualMeasuresWs; import org.sonar.server.measure.ws.TimeMachineWs; import org.sonar.server.metric.CoreCustomMetrics; import org.sonar.server.metric.ws.MetricsWsModule; -import org.sonar.server.notifications.NotificationCenter; -import org.sonar.server.notifications.NotificationService; -import org.sonar.server.notifications.email.AlertsEmailTemplate; -import org.sonar.server.notifications.email.EmailNotificationChannel; +import org.sonar.server.notification.NotificationCenter; +import org.sonar.server.notification.NotificationService; +import org.sonar.server.notification.email.AlertsEmailTemplate; +import org.sonar.server.notification.email.EmailNotificationChannel; import org.sonar.server.permission.InternalPermissionService; import org.sonar.server.permission.InternalPermissionTemplateService; import org.sonar.server.permission.PermissionFinder; diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/SendIssueNotificationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/SendIssueNotificationsStepTest.java index 7fb81786e6c..a66e2c4085e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/SendIssueNotificationsStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/SendIssueNotificationsStepTest.java @@ -40,7 +40,7 @@ import org.sonar.server.computation.issue.RuleCache; import org.sonar.server.issue.notification.IssueChangeNotification; import org.sonar.server.issue.notification.NewIssuesNotification; import org.sonar.server.issue.notification.NewIssuesNotificationFactory; -import org.sonar.server.notifications.NotificationService; +import org.sonar.server.notification.NotificationService; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeastOnce; diff --git a/server/sonar-server/src/test/java/org/sonar/server/event/NewAlertsTest.java b/server/sonar-server/src/test/java/org/sonar/server/event/NewAlertsTest.java index 49bb6f7e6f0..d2b2f653eb9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/event/NewAlertsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/event/NewAlertsTest.java @@ -24,8 +24,8 @@ import com.google.common.collect.Multimap; import org.junit.Test; import org.sonar.api.notifications.Notification; import org.sonar.api.notifications.NotificationChannel; -import org.sonar.core.notification.NotificationDispatcher; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationDispatcher; +import org.sonar.server.notification.NotificationManager; import static org.mockito.Mockito.*; diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/ChangesOnMyIssueNotificationDispatcherTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/ChangesOnMyIssueNotificationDispatcherTest.java index fdcefadb1ba..a11fd69465c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/ChangesOnMyIssueNotificationDispatcherTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/ChangesOnMyIssueNotificationDispatcherTest.java @@ -27,9 +27,9 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.sonar.api.notifications.*; -import org.sonar.core.notification.NotificationDispatcher; -import org.sonar.core.notification.NotificationDispatcherMetadata; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationDispatcher; +import org.sonar.server.notification.NotificationDispatcherMetadata; +import org.sonar.server.notification.NotificationManager; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/DoNotFixNotificationDispatcherTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/DoNotFixNotificationDispatcherTest.java index 4f42809dfb7..91061b4cb7e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/DoNotFixNotificationDispatcherTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/DoNotFixNotificationDispatcherTest.java @@ -25,9 +25,9 @@ import org.junit.Test; import org.sonar.api.issue.Issue; import org.sonar.api.notifications.Notification; import org.sonar.api.notifications.NotificationChannel; -import org.sonar.core.notification.NotificationDispatcher; -import org.sonar.core.notification.NotificationDispatcherMetadata; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationDispatcher; +import org.sonar.server.notification.NotificationDispatcherMetadata; +import org.sonar.server.notification.NotificationManager; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesNotificationDispatcherTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesNotificationDispatcherTest.java index 9173ef7227c..b697cdfe159 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesNotificationDispatcherTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/MyNewIssuesNotificationDispatcherTest.java @@ -26,8 +26,8 @@ import org.junit.Before; import org.junit.Test; import org.sonar.api.notifications.Notification; import org.sonar.api.notifications.NotificationChannel; -import org.sonar.core.notification.NotificationDispatcher; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationDispatcher; +import org.sonar.server.notification.NotificationManager; import static org.mockito.Mockito.*; diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationDispatcherTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationDispatcherTest.java index 656d3bb4231..ec975b52966 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationDispatcherTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/notification/NewIssuesNotificationDispatcherTest.java @@ -25,8 +25,8 @@ import org.junit.Before; import org.junit.Test; import org.sonar.api.notifications.Notification; import org.sonar.api.notifications.NotificationChannel; -import org.sonar.core.notification.NotificationDispatcher; -import org.sonar.core.notification.NotificationManager; +import org.sonar.server.notification.NotificationDispatcher; +import org.sonar.server.notification.NotificationManager; import static org.mockito.Mockito.*; diff --git a/server/sonar-server/src/test/java/org/sonar/server/notification/DefaultNotificationManagerTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/DefaultNotificationManagerTest.java new file mode 100644 index 00000000000..e534646911c --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/DefaultNotificationManagerTest.java @@ -0,0 +1,180 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.notification; + +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationChannel; +import org.sonar.core.notification.db.NotificationQueueDao; +import org.sonar.core.notification.db.NotificationQueueDto; +import org.sonar.core.properties.PropertiesDao; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +import java.io.InvalidClassException; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.only; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class DefaultNotificationManagerTest extends AbstractDbUnitTestCase { + + private DefaultNotificationManager manager; + + @Mock + private PropertiesDao propertiesDao; + + @Mock + private NotificationDispatcher dispatcher; + + @Mock + private NotificationChannel emailChannel; + + @Mock + private NotificationChannel twitterChannel; + + @Mock + private NotificationQueueDao notificationQueueDao; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(dispatcher.getKey()).thenReturn("NewViolations"); + when(emailChannel.getKey()).thenReturn("Email"); + when(twitterChannel.getKey()).thenReturn("Twitter"); + + manager = new DefaultNotificationManager(new NotificationChannel[] {emailChannel, twitterChannel}, notificationQueueDao, propertiesDao); + } + + @Test + public void shouldProvideChannelList() { + assertThat(manager.getChannels()).containsOnly(emailChannel, twitterChannel); + + manager = new DefaultNotificationManager(notificationQueueDao, propertiesDao); + assertThat(manager.getChannels()).hasSize(0); + } + + @Test + public void shouldPersist() { + Notification notification = new Notification("test"); + manager.scheduleForSending(notification); + + verify(notificationQueueDao, only()).insert(any(List.class)); + } + + @Test + public void shouldGetFromQueueAndDelete() { + Notification notification = new Notification("test"); + NotificationQueueDto dto = NotificationQueueDto.toNotificationQueueDto(notification); + List<NotificationQueueDto> dtos = Arrays.asList(dto); + when(notificationQueueDao.findOldest(1)).thenReturn(dtos); + + assertThat(manager.getFromQueue()).isNotNull(); + + InOrder inOrder = inOrder(notificationQueueDao); + inOrder.verify(notificationQueueDao).findOldest(1); + inOrder.verify(notificationQueueDao).delete(dtos); + } + + // SONAR-4739 + @Test + public void shouldNotFailWhenUnableToDeserialize() throws Exception { + NotificationQueueDto dto1 = mock(NotificationQueueDto.class); + when(dto1.toNotification()).thenThrow(new InvalidClassException("Pouet")); + List<NotificationQueueDto> dtos = Arrays.asList(dto1); + when(notificationQueueDao.findOldest(1)).thenReturn(dtos); + + manager = spy(manager); + assertThat(manager.getFromQueue()).isNull(); + assertThat(manager.getFromQueue()).isNull(); + + verify(manager, times(1)).logDeserializationIssue(); + } + + @Test + public void shouldFindNoRecipient() { + assertThat(manager.findSubscribedRecipientsForDispatcher(dispatcher, 45).asMap().entrySet()).hasSize(0); + } + + @Test + public void shouldFindSubscribedRecipientForGivenResource() { + when(propertiesDao.findUsersForNotification("NewViolations", "Email", 45L)).thenReturn(Lists.newArrayList("user1", "user2")); + when(propertiesDao.findUsersForNotification("NewViolations", "Email", null)).thenReturn(Lists.newArrayList("user1", "user3")); + when(propertiesDao.findUsersForNotification("NewViolations", "Twitter", 56L)).thenReturn(Lists.newArrayList("user2")); + when(propertiesDao.findUsersForNotification("NewViolations", "Twitter", null)).thenReturn(Lists.newArrayList("user3")); + when(propertiesDao.findUsersForNotification("NewAlerts", "Twitter", null)).thenReturn(Lists.newArrayList("user4")); + + Multimap<String, NotificationChannel> multiMap = manager.findSubscribedRecipientsForDispatcher(dispatcher, 45); + assertThat(multiMap.entries()).hasSize(4); + + Map<String, Collection<NotificationChannel>> map = multiMap.asMap(); + assertThat(map.get("user1")).containsOnly(emailChannel); + assertThat(map.get("user2")).containsOnly(emailChannel); + assertThat(map.get("user3")).containsOnly(emailChannel, twitterChannel); + assertThat(map.get("user4")).isNull(); + } + + @Test + public void shouldFindSubscribedRecipientForNoResource() { + when(propertiesDao.findUsersForNotification("NewViolations", "Email", 45L)).thenReturn(Lists.newArrayList("user1", "user2")); + when(propertiesDao.findUsersForNotification("NewViolations", "Email", null)).thenReturn(Lists.newArrayList("user1", "user3")); + when(propertiesDao.findUsersForNotification("NewViolations", "Twitter", 56L)).thenReturn(Lists.newArrayList("user2")); + when(propertiesDao.findUsersForNotification("NewViolations", "Twitter", null)).thenReturn(Lists.newArrayList("user3")); + when(propertiesDao.findUsersForNotification("NewAlerts", "Twitter", null)).thenReturn(Lists.newArrayList("user4")); + + Multimap<String, NotificationChannel> multiMap = manager.findSubscribedRecipientsForDispatcher(dispatcher, (Integer) null); + assertThat(multiMap.entries()).hasSize(3); + + Map<String, Collection<NotificationChannel>> map = multiMap.asMap(); + assertThat(map.get("user1")).containsOnly(emailChannel); + assertThat(map.get("user3")).containsOnly(emailChannel, twitterChannel); + assertThat(map.get("user2")).isNull(); + assertThat(map.get("user4")).isNull(); + } + + @Test + public void findNotificationSubscribers() { + when(propertiesDao.findNotificationSubscribers("NewViolations", "Email", "struts")).thenReturn(Lists.newArrayList("user1", "user2")); + when(propertiesDao.findNotificationSubscribers("NewViolations", "Twitter", "struts")).thenReturn(Lists.newArrayList("user2")); + + Multimap<String, NotificationChannel> multiMap = manager.findNotificationSubscribers(dispatcher, "struts"); + assertThat(multiMap.entries()).hasSize(3); + + Map<String, Collection<NotificationChannel>> map = multiMap.asMap(); + assertThat(map.get("user1")).containsOnly(emailChannel); + assertThat(map.get("user2")).containsOnly(emailChannel, twitterChannel); + assertThat(map.get("other")).isNull(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/notifications/NotificationCenterTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationCenterTest.java index ecd6ef52117..e4d7b28fca5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/notifications/NotificationCenterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationCenterTest.java @@ -17,14 +17,13 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.notifications; +package org.sonar.server.notification; 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.core.notification.NotificationDispatcherMetadata; import static org.assertj.core.api.Assertions.assertThat; diff --git a/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationChannelTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationChannelTest.java new file mode 100644 index 00000000000..e0a0c823bcf --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationChannelTest.java @@ -0,0 +1,44 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.notification; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import org.junit.Test; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationChannel; + +public class NotificationChannelTest { + + @Test + public void defaultMethods() { + NotificationChannel channel = new FakeNotificationChannel(); + assertThat(channel.getKey(), is("FakeNotificationChannel")); + assertThat(channel.toString(), is("FakeNotificationChannel")); + } + + class FakeNotificationChannel extends NotificationChannel { + @Override + public void deliver(Notification notification, String username) { + } + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationDispatcherMetadataTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationDispatcherMetadataTest.java new file mode 100644 index 00000000000..7874ab50f45 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationDispatcherMetadataTest.java @@ -0,0 +1,46 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.notification; + +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.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/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationDispatcherTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationDispatcherTest.java new file mode 100644 index 00000000000..e6ec1a7d450 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationDispatcherTest.java @@ -0,0 +1,101 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.notification; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationChannel; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class NotificationDispatcherTest { + + @Mock + private NotificationChannel channel; + + @Mock + private Notification notification; + + @Mock + private NotificationDispatcher.Context context; + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + when(notification.getType()).thenReturn("event1"); + } + + @Test + public void defaultMethods() { + NotificationDispatcher dispatcher = new FakeGenericNotificationDispatcher(); + assertThat(dispatcher.getKey(), is("FakeGenericNotificationDispatcher")); + assertThat(dispatcher.toString(), is("FakeGenericNotificationDispatcher")); + } + + @Test + public void shouldAlwaysRunDispatchForGenericDispatcher() { + NotificationDispatcher dispatcher = new FakeGenericNotificationDispatcher(); + dispatcher.performDispatch(notification, context); + + verify(context, times(1)).addUser("user1", channel); + } + + @Test + public void shouldNotAlwaysRunDispatchForSpecificDispatcher() { + NotificationDispatcher dispatcher = new FakeSpecificNotificationDispatcher(); + + // a "event1" notif is sent + dispatcher.performDispatch(notification, context); + verify(context, never()).addUser("user1", channel); + + // now, a "specific-event" notif is sent + when(notification.getType()).thenReturn("specific-event"); + dispatcher.performDispatch(notification, context); + verify(context, times(1)).addUser("user1", channel); + } + + class FakeGenericNotificationDispatcher extends NotificationDispatcher { + @Override + public void dispatch(Notification notification, Context context) { + context.addUser("user1", channel); + } + } + + class FakeSpecificNotificationDispatcher extends NotificationDispatcher { + + public FakeSpecificNotificationDispatcher() { + super("specific-event"); + } + + @Override + public void dispatch(Notification notification, Context context) { + context.addUser("user1", channel); + } + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationServiceTest.java index c818dee6eac..515c4279864 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/notifications/NotificationServiceTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationServiceTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.notifications; +package org.sonar.server.notification; import com.google.common.collect.Sets; import org.junit.Test; @@ -26,8 +26,6 @@ import org.mockito.stubbing.Answer; import org.sonar.api.config.Settings; import org.sonar.api.notifications.Notification; import org.sonar.api.notifications.NotificationChannel; -import org.sonar.core.notification.NotificationDispatcher; -import org.sonar.core.notification.DefaultNotificationManager; import org.sonar.core.properties.PropertiesDao; import org.sonar.jpa.session.DatabaseSessionFactory; import org.sonar.server.db.DbClient; diff --git a/server/sonar-server/src/test/java/org/sonar/server/notifications/NotificationTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationTest.java index 2c7c9194f9c..d90b000212c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/notifications/NotificationTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/NotificationTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.notifications; +package org.sonar.server.notification; import org.junit.Before; import org.junit.Test; diff --git a/server/sonar-server/src/test/java/org/sonar/server/notifications/email/AlertsEmailTemplateTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/email/AlertsEmailTemplateTest.java index 3834df8b9e8..3d81a495628 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/notifications/email/AlertsEmailTemplateTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/email/AlertsEmailTemplateTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.notifications.email; +package org.sonar.server.notification.email; import org.junit.Before; import org.junit.Test; diff --git a/server/sonar-server/src/test/java/org/sonar/server/notifications/email/EmailNotificationChannelTest.java b/server/sonar-server/src/test/java/org/sonar/server/notification/email/EmailNotificationChannelTest.java index 3c5e94587af..e7cbcce0d57 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/notifications/email/EmailNotificationChannelTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/notification/email/EmailNotificationChannelTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.server.notifications.email; +package org.sonar.server.notification.email; import java.io.IOException; import java.net.ServerSocket; |