diff options
author | Evgeny Mandrikov <mandrikov@gmail.com> | 2011-07-21 11:45:41 +0400 |
---|---|---|
committer | Evgeny Mandrikov <mandrikov@gmail.com> | 2011-07-22 18:52:15 +0400 |
commit | 957e62ce77e23d31d59f9369657e91a9dd616c84 (patch) | |
tree | b78bf8831d41c82fa34cd071a3783f756f08d745 /sonar-server | |
parent | e0e528211faad3fdf469c83bcbc7aecf6c25a234 (diff) | |
download | sonarqube-957e62ce77e23d31d59f9369657e91a9dd616c84.tar.gz sonarqube-957e62ce77e23d31d59f9369657e91a9dd616c84.zip |
SONAR-2607 Provide email notifications on review changes
* Add email templates.
* Add server component - UserFinder.
Diffstat (limited to 'sonar-server')
6 files changed, 109 insertions, 87 deletions
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 b88cf62146b..b408a05bfd7 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 @@ -136,9 +136,9 @@ public class NotificationService implements ServerComponent { } for (Map.Entry<String, Collection<NotificationChannel>> entry : recipients.asMap().entrySet()) { String username = entry.getKey(); - Collection<NotificationChannel> channels = entry.getValue(); - LOG.info("For user {} via {}", username, channels); - for (NotificationChannel channel : channels) { + Collection<NotificationChannel> userChannels = entry.getValue(); + LOG.info("For user {} via {}", username, userChannels); + for (NotificationChannel channel : userChannels) { channel.deliver(notification, username); } } diff --git a/sonar-server/src/main/java/org/sonar/server/notifications/reviews/ReviewsNotificationManager.java b/sonar-server/src/main/java/org/sonar/server/notifications/reviews/ReviewsNotificationManager.java index e8200bd4b06..a89a5667acf 100644 --- a/sonar-server/src/main/java/org/sonar/server/notifications/reviews/ReviewsNotificationManager.java +++ b/sonar-server/src/main/java/org/sonar/server/notifications/reviews/ReviewsNotificationManager.java @@ -19,49 +19,69 @@ */ package org.sonar.server.notifications.reviews; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; import org.sonar.api.ServerComponent; -import org.sonar.api.database.model.Review; -import org.sonar.api.database.model.User; import org.sonar.api.notifications.Notification; import org.sonar.api.notifications.NotificationManager; -import org.sonar.jpa.session.DatabaseSessionFactory; + +import com.google.common.collect.Sets; /** * @since 2.10 */ public class ReviewsNotificationManager implements ServerComponent { - private DatabaseSessionFactory sessionFactory; private NotificationManager notificationManager; - public ReviewsNotificationManager(DatabaseSessionFactory sessionFactory, NotificationManager notificationManager) { - this.sessionFactory = sessionFactory; + public ReviewsNotificationManager(NotificationManager notificationManager) { this.notificationManager = notificationManager; } /** - * Visibility has been relaxed for tests. + * @param reviewId id of review, which was modified + * @param author author of change (username) + * @param creator author of review (username) + * @param assignee current assignee (username) + * @param oldComment old text of comment + * @param comment new text of comment */ - User getUserById(Integer id) { - return sessionFactory.getSession().getEntity(User.class, id); + public void notifyCommentChanged(Long reviewId, String author, String creator, String assignee, String oldComment, String newComment) { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", String.valueOf(reviewId)) + .setFieldValue("author", author) + .setFieldValue("creator", creator) + .setFieldValue("assignee", assignee) + .setFieldValue("old.comment", oldComment) + .setFieldValue("new.comment", newComment); + notificationManager.scheduleForSending(notification); } /** - * Visibility has been relaxed for tests. + * @param reviewId reviewId id of review, which was modified + * @param author author of change (username) + * @param oldValues map of old values + * @param newValues map of new values */ - Review getReviewById(Long id) { - return sessionFactory.getSession().getEntity(Review.class, id); - } - - public void notifyCommentAdded(Long reviewId, Integer userId, String comment) { - Review review = getReviewById(reviewId); - User author = getUserById(userId); - - Notification notification = new Notification("review"); - notification // FIXME include info about review - .setFieldValue("author", author.getLogin()) - .setFieldValue("comment", comment); - + public void notifyChanged(Long reviewId, String author, Map<String, String> oldValues, Map<String, String> newValues) { + Notification notification = new Notification("review-changed") + .setFieldValue("reviewId", author) + .setFieldValue("author", author) + .setFieldValue("creator", newValues.get("creator")) + .setFieldValue("assignee", newValues.get("assignee")); + Set<String> fields = Sets.newHashSet(); + fields.addAll(oldValues.keySet()); + fields.addAll(newValues.keySet()); + for (String field : fields) { + String oldValue = oldValues.get(field); + String newValue = newValues.get(field); + if ( !StringUtils.equals(oldValue, newValue)) { + notification.setFieldValue("new." + field, newValue); + notification.setFieldValue("old." + field, oldValue); + } + } notificationManager.scheduleForSending(notification); } 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 df234f0c490..7b5ef8fac7f 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 @@ -40,6 +40,7 @@ import org.sonar.api.utils.TimeProfiler; import org.sonar.core.components.DefaultMetricFinder; import org.sonar.core.components.DefaultModelFinder; import org.sonar.core.components.DefaultRuleFinder; +import org.sonar.core.components.DefaultUserFinder; import org.sonar.core.notifications.DefaultNotificationManager; import org.sonar.jpa.dao.DaoFacade; import org.sonar.jpa.dao.MeasuresDao; @@ -185,6 +186,7 @@ public final class Platform { servicesContainer.as(Characteristics.CACHE).addComponent(ProfilesConsole.class); servicesContainer.as(Characteristics.CACHE).addComponent(RulesConsole.class); servicesContainer.as(Characteristics.CACHE).addComponent(JRubyI18n.class); + servicesContainer.as(Characteristics.CACHE).addComponent(DefaultUserFinder.class); // Notifications servicesContainer.as(Characteristics.CACHE).addComponent(NotificationService.class); diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb index 94df7aed6d6..d4fe68c3808 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/review.rb @@ -54,15 +54,14 @@ class Review < ActiveRecord::Base # REVIEW CORE METHODS # # - + # params are mandatory: # - :user # - :text def create_comment(params={}) comment = comments.create!(params) touch - - Java::OrgSonarServerUi::JRubyFacade.getInstance().getReviewsNotificationManager().notifyCommentAdded(id.to_i, comment.user.id.to_i, comment.text.to_java) + # TODO notification_manager.notifyCommentChanged(id.to_i, current_user.login.to_java, self.user.login.to_java, self.assignee.login.to_java, nil, comment.text.to_java) end def edit_comment(comment_id, comment_text) @@ -76,25 +75,61 @@ class Review < ActiveRecord::Base def edit_last_comment(comment_text) comment=comments.last + old_comment_text=comment.text comment.text=comment_text comment.save! touch + # TODO notification_manager.notifyCommentChanged(id.to_i, current_user.login.to_java, self.user.login.to_java, self.assignee.login.to_java, old_comment.to_java, comment.text.to_java) end - + def delete_comment(comment_id) comment=comments.find(comment_id) comments.pop if comment + old_comment_text=comment.text comment.delete touch + # TODO notification_manager.notifyCommentChanged(id.to_i, current_user.login.to_java, self.user.login.to_java, self.assignee.login.to_java, old_comment_text.to_java, nil) end end - + + def notification_manager + Java::OrgSonarServerUi::JRubyFacade.getInstance().getReviewsNotificationManager() + end + + def to_java_map() + map = java.util.HashMap.new({ + :creator => user.login.to_java, + :assignee => assignee == nil ? nil : assignee.login.to_java, + :status => status.to_java, + :resolution => resolution.to_java + }) + map + end + def reassign(user) + old = self.to_java_map self.assignee = user self.save! + # TODO notification_manager.notifyChanged(id.to_i, current_user.login.to_java, old, to_java_map) end - + + def reopen + old = self.to_java_map + self.status = STATUS_REOPENED + self.resolution = nil + self.save! + # TODO notification_manager.notifyChanged(id.to_i, current_user.login.to_java, old, to_java_map) + end + + def resolve + old = self.to_java_map + self.status = STATUS_RESOLVED + self.resolution = 'FIXED' + self.save! + # TODO notification_manager.notifyChanged(id.to_i, current_user.login.to_java, old, to_java_map) + end + # params are mandatory: # - :user (mandatory) # - :text (mandatory) @@ -112,13 +147,15 @@ class Review < ActiveRecord::Base end end create_comment(:user => params[:user], :text => params[:text]) + old = self.to_java_map self.assignee = nil self.status = is_false_positive ? STATUS_RESOLVED : STATUS_REOPENED self.resolution = is_false_positive ? 'FALSE-POSITIVE' : nil self.save! + # TODO notification_manager.notifyChanged(id.to_i, current_user.login.to_java, old, to_java_map) end end - + def false_positive resolution == 'FALSE-POSITIVE' end @@ -143,20 +180,6 @@ class Review < ActiveRecord::Base status == STATUS_OPEN end - def reopen - self.status = STATUS_REOPENED - self.resolution = nil - self.save! - end - - def resolve - self.status = STATUS_RESOLVED - self.resolution = 'FIXED' - self.save! - end - - - # # # SEARCH METHODS diff --git a/sonar-server/src/test/java/org/sonar/server/notifications/reviews/ReviewsNotificationManagerTest.java b/sonar-server/src/test/java/org/sonar/server/notifications/reviews/ReviewsNotificationManagerTest.java index 8e0eaba6953..187d3e965b3 100644 --- a/sonar-server/src/test/java/org/sonar/server/notifications/reviews/ReviewsNotificationManagerTest.java +++ b/sonar-server/src/test/java/org/sonar/server/notifications/reviews/ReviewsNotificationManagerTest.java @@ -19,39 +19,31 @@ */ package org.sonar.server.notifications.reviews; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; import org.junit.Before; -import org.junit.Test; -import org.sonar.api.database.model.Review; -import org.sonar.api.database.model.User; -import org.sonar.jpa.test.AbstractDbUnitTestCase; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.sonar.api.notifications.Notification; +import org.sonar.api.notifications.NotificationManager; -public class ReviewsNotificationManagerTest extends AbstractDbUnitTestCase { +public class ReviewsNotificationManagerTest { // FIXME implement + private Notification notification; private ReviewsNotificationManager manager; @Before public void setUp() { - setupData(getClass().getResourceAsStream("fixture.xml")); - manager = new ReviewsNotificationManager(getSessionFactory(), null); - } - - @Test - public void shouldGetReviewById() { - Review review = manager.getReviewById(3L); - assertThat(review.getUserId(), is(1)); - assertThat(review.getAssigneeId(), is(2)); - assertThat(review.getTitle(), is("Review #3")); - } - - @Test - public void shouldGetUserById() { - User user = manager.getUserById(1); - assertThat(user.getLogin(), is("simon")); - assertThat(user.getName(), is("Simon Brandhof")); - assertThat(user.getEmail(), is("simon.brandhof@sonarsource.com")); + NotificationManager delegate = mock(NotificationManager.class); + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + notification = (Notification) invocation.getArguments()[0]; + return null; + } + }).when(delegate).scheduleForSending(any(Notification.class)); + manager = new ReviewsNotificationManager(delegate); } } diff --git a/sonar-server/src/test/resources/org/sonar/server/notifications/reviews/fixture.xml b/sonar-server/src/test/resources/org/sonar/server/notifications/reviews/fixture.xml deleted file mode 100644 index d9a64d90337..00000000000 --- a/sonar-server/src/test/resources/org/sonar/server/notifications/reviews/fixture.xml +++ /dev/null @@ -1,15 +0,0 @@ -<dataset> - - <users id="1" login="simon" name="Simon Brandhof" email="simon.brandhof@sonarsource.com" /> - <users id="2" login="godin" name="Evgeny Mandrikov" email="evgeny.mandrikov@sonarsource.com" /> - - <!-- Review created by Simon and assigned to him --> - <reviews id="1" user_id="1" assignee_id="1" title="Review #1" /> - - <!-- Review created by Evgeny and not assigned --> - <reviews id="2" user_id="2" assignee_id="[null]" title="Review #2" /> - - <!-- Review created by Simon and assigned to Evgeny --> - <reviews id="3" user_id="1" assignee_id="2" title="Review #3" /> - -</dataset>
\ No newline at end of file |