this.db = db;
this.myBatis = myBatis;
- Map<Class, DaoComponent> map = new IdentityHashMap<Class, DaoComponent>();
+ Map<Class, DaoComponent> map = new IdentityHashMap<>();
for (DaoComponent daoComponent : daoComponents) {
map.put(daoComponent.getClass(), daoComponent);
}
import java.util.Map;
/**
- * Create registered indices in Elasticsearch.
+ * Creates/deletes all indices in Elasticsearch during server startup.
*/
public class IndexCreator implements ServerComponent, Startable {
import java.util.Map;
+/**
+ * This class collects definitions of all Elasticsearch indices during server startup
+ */
public class IndexRegistry implements ServerComponent, Startable {
/**
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
+import org.picocontainer.Startable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.Properties;
import org.sonar.api.notifications.NotificationDispatcher;
import org.sonar.api.utils.TimeProfiler;
import org.sonar.core.notification.DefaultNotificationManager;
-import org.sonar.jpa.session.DatabaseSessionFactory;
import java.util.Arrays;
import java.util.Collection;
project = false,
global = false)
})
-public class NotificationService implements ServerComponent {
+public class NotificationService implements ServerComponent, Startable {
private static final Logger LOG = LoggerFactory.getLogger(NotificationService.class);
private final long delayBeforeReportingStatusInSeconds;
private final DefaultNotificationManager manager;
private final NotificationDispatcher[] dispatchers;
- private final DatabaseSessionFactory databaseSessionFactory;
private ScheduledExecutorService executorService;
private boolean stopping = false;
/**
* Constructor for {@link NotificationService}
*/
- public NotificationService(Settings settings, DefaultNotificationManager manager, DatabaseSessionFactory databaseSessionFactory, NotificationDispatcher[] dispatchers) {
- this.databaseSessionFactory = databaseSessionFactory;
+ public NotificationService(Settings settings, DefaultNotificationManager manager, NotificationDispatcher[] dispatchers) {
delayInSeconds = settings.getLong(PROPERTY_DELAY);
delayBeforeReportingStatusInSeconds = settings.getLong(PROPERTY_DELAY_BEFORE_REPORTING_STATUS);
this.manager = manager;
/**
* Default constructor when no channels.
*/
- public NotificationService(Settings settings, DefaultNotificationManager manager, DatabaseSessionFactory databaseSessionFactory) {
- this(settings, manager, databaseSessionFactory, new NotificationDispatcher[0]);
+ public NotificationService(Settings settings, DefaultNotificationManager manager) {
+ this(settings, manager, new NotificationDispatcher[0]);
LOG.warn("There is no dispatcher - all notifications will be ignored!");
}
+ @Override
public void start() {
executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleWithFixedDelay(new Runnable() {
processQueue();
} catch (Exception e) {
LOG.error("Error in NotificationService", e);
- } finally {
- // Free Hibernate session
- databaseSessionFactory.clear();
}
}
}, 0, delayInSeconds, TimeUnit.SECONDS);
LOG.info("Notification service started (delay {} sec.)", delayInSeconds);
}
+ @Override
public void stop() {
try {
stopping = true;
--- /dev/null
+/*
+ * 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.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.notifications;
+
+import javax.annotation.ParametersAreNonnullByDefault;
import org.sonar.api.web.UserRole;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.DbSession;
-import org.sonar.core.source.db.FileSourceDao;
import org.sonar.server.db.DbClient;
import org.sonar.server.user.UserSession;
public class HashAction implements RequestHandler {
private final DbClient dbClient;
- private final FileSourceDao fileSourceDao;
- public HashAction(DbClient dbClient, FileSourceDao fileSourceDao) {
+ public HashAction(DbClient dbClient) {
this.dbClient = dbClient;
- this.fileSourceDao = fileSourceDao;
}
void define(WebService.NewController controller) {
String componentKey = request.mandatoryParam("key");
UserSession.get().checkComponentPermission(UserRole.CODEVIEWER, componentKey);
ComponentDto component = dbClient.componentDao().getByKey(session, componentKey);
- String lineHashes = fileSourceDao.selectLineHashes(component.uuid(), session);
+ String lineHashes = dbClient.fileSourceDao().selectLineHashes(component.uuid(), session);
if (lineHashes == null) {
response.noContent();
} else {
import org.sonar.api.notifications.NotificationChannel;
import org.sonar.api.notifications.NotificationDispatcher;
import org.sonar.core.notification.DefaultNotificationManager;
-import org.sonar.jpa.session.DatabaseSessionFactory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.same;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
public class NotificationServiceTest {
private static String CREATOR_SIMON = "simon";
private NotificationService service;
- private void setUpMocks(String creator, String assignee) {
+ private void setUpMocks() {
when(emailChannel.getKey()).thenReturn("email");
when(gtalkChannel.getKey()).thenReturn("gtalk");
when(commentOnReviewAssignedToMe.getKey()).thenReturn("comment on review assigned to me");
Settings settings = new Settings().setProperty("sonar.notifications.delay", 1L);
- service = new NotificationService(settings, manager, mock(DatabaseSessionFactory.class),
+ service = new NotificationService(settings, manager,
new NotificationDispatcher[] {commentOnReviewAssignedToMe, commentOnReviewCreatedByMe});
}
*/
@Test
public void scenario1() {
- setUpMocks(CREATOR_SIMON, ASSIGNEE_SIMON);
+ setUpMocks();
doAnswer(addUser(ASSIGNEE_SIMON, emailChannel)).when(commentOnReviewAssignedToMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));
doAnswer(addUser(CREATOR_SIMON, emailChannel)).when(commentOnReviewCreatedByMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));
*/
@Test
public void scenario2() {
- setUpMocks(CREATOR_EVGENY, ASSIGNEE_SIMON);
+ setUpMocks();
doAnswer(addUser(ASSIGNEE_SIMON, emailChannel)).when(commentOnReviewAssignedToMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));
doAnswer(addUser(CREATOR_EVGENY, gtalkChannel)).when(commentOnReviewCreatedByMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));
*/
@Test
public void scenario3() {
- setUpMocks(CREATOR_EVGENY, ASSIGNEE_SIMON);
+ setUpMocks();
doAnswer(addUser(ASSIGNEE_SIMON, new NotificationChannel[] {emailChannel, gtalkChannel}))
.when(commentOnReviewAssignedToMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));
*/
@Test
public void scenario4() {
- setUpMocks(CREATOR_EVGENY, ASSIGNEE_SIMON);
+ setUpMocks();
service.start();
service.stop();
// SONAR-4548
@Test
public void shouldNotStopWhenException() {
- setUpMocks(CREATOR_SIMON, ASSIGNEE_SIMON);
+ setUpMocks();
when(manager.getFromQueue()).thenThrow(new RuntimeException("Unexpected exception")).thenReturn(notification).thenReturn(null);
doAnswer(addUser(ASSIGNEE_SIMON, emailChannel)).when(commentOnReviewAssignedToMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));
doAnswer(addUser(CREATOR_SIMON, emailChannel)).when(commentOnReviewCreatedByMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));
@Test
public void shouldNotAddNullAsUser() {
- setUpMocks(CREATOR_EVGENY, ASSIGNEE_SIMON);
+ setUpMocks();
doAnswer(addUser(null, gtalkChannel)).when(commentOnReviewCreatedByMe).dispatch(same(notification), any(NotificationDispatcher.Context.class));
service.start();
@Test
public void shouldReturnDispatcherList() {
- setUpMocks(CREATOR_SIMON, ASSIGNEE_SIMON);
+ setUpMocks();
assertThat(service.getDispatchers()).containsOnly(commentOnReviewAssignedToMe, commentOnReviewCreatedByMe);
}
public void shouldReturnNoDispatcher() {
Settings settings = new Settings().setProperty("sonar.notifications.delay", 1L);
- service = new NotificationService(settings, manager, mock(DatabaseSessionFactory.class));
+ service = new NotificationService(settings, manager);
assertThat(service.getDispatchers()).hasSize(0);
}
@Test
public void shouldLogEvery10Minutes() throws InterruptedException {
- setUpMocks(CREATOR_EVGENY, ASSIGNEE_SIMON);
+ setUpMocks();
// Emulate 2 notifications in DB
when(manager.getFromQueue()).thenReturn(notification).thenReturn(notification).thenReturn(null);
when(manager.count()).thenReturn(1L).thenReturn(0L);
@Before
public void setUp() throws Exception {
when(dbClient.componentDao()).thenReturn(componentDao);
+ when(dbClient.fileSourceDao()).thenReturn(fileSourceDao);
when(dbClient.openSession(false)).thenReturn(mock(DbSession.class));
tester = new WsTester(
new SourcesWs(
mock(RawAction.class),
mock(ScmAction.class),
mock(LinesAction.class),
- new HashAction(dbClient, fileSourceDao),
+ new HashAction(dbClient),
mock(IndexAction.class)
)
- );
+ );
}
@Test
import org.junit.Test;
import org.sonar.api.server.ws.WebService;
-import org.sonar.core.source.db.FileSourceDao;
import org.sonar.server.component.ComponentService;
import org.sonar.server.db.DbClient;
import org.sonar.server.source.HtmlSourceDecorator;
RawAction rawAction = new RawAction(mock(DbClient.class), mock(SourceService.class));
ScmAction scmAction = new ScmAction(mock(SourceService.class), new ScmWriter());
LinesAction linesAction = new LinesAction(mock(SourceLineIndex.class), mock(HtmlSourceDecorator.class), mock(ComponentService.class));
- HashAction hashAction = new HashAction(mock(DbClient.class), mock(FileSourceDao.class));
+ HashAction hashAction = new HashAction(mock(DbClient.class));
IndexAction indexAction = new IndexAction(mock(DbClient.class), mock(SourceService.class));
WsTester tester = new WsTester(new SourcesWs(showAction, rawAction, scmAction, linesAction, hashAction, indexAction));
import org.sonar.api.BatchComponent;
import org.sonar.api.ServerComponent;
+import org.sonar.core.persistence.DaoComponent;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import javax.annotation.CheckForNull;
-public class FileSourceDao implements BatchComponent, ServerComponent {
+public class FileSourceDao implements BatchComponent, ServerComponent, DaoComponent {
private final MyBatis mybatis;