From f2b796849290393c75a3b52bf51dbb544da0d3dd Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Mon, 24 Mar 2014 13:38:18 +0100 Subject: [PATCH] SONAR-5056 Use restore to populate debt model at startup --- .../server/debt/DebtModelSynchronizer.java | 107 -------------- .../server/platform/ServerComponents.java | 3 +- .../server/startup/RegisterDebtModel.java | 15 +- .../debt/DebtModelSynchronizerTest.java | 132 ------------------ .../server/startup/RegisterDebtModelTest.java | 43 +++++- 5 files changed, 48 insertions(+), 252 deletions(-) delete mode 100644 sonar-server/src/main/java/org/sonar/server/debt/DebtModelSynchronizer.java delete mode 100644 sonar-server/src/test/java/org/sonar/server/debt/DebtModelSynchronizerTest.java diff --git a/sonar-server/src/main/java/org/sonar/server/debt/DebtModelSynchronizer.java b/sonar-server/src/main/java/org/sonar/server/debt/DebtModelSynchronizer.java deleted file mode 100644 index f6e3f8b331c..00000000000 --- a/sonar-server/src/main/java/org/sonar/server/debt/DebtModelSynchronizer.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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.debt; - -import org.apache.commons.io.IOUtils; -import org.apache.ibatis.session.SqlSession; -import org.sonar.api.ServerExtension; -import org.sonar.api.server.debt.DebtCharacteristic; -import org.sonar.core.persistence.MyBatis; -import org.sonar.core.technicaldebt.TechnicalDebtModelRepository; -import org.sonar.core.technicaldebt.db.CharacteristicDao; -import org.sonar.core.technicaldebt.db.CharacteristicDto; - -import javax.annotation.Nullable; - -import java.io.Reader; -import java.util.List; - -import static com.google.common.collect.Lists.newArrayList; - -// TODO replace this by DebtModelRestore -public class DebtModelSynchronizer implements ServerExtension { - - private final MyBatis mybatis; - private final CharacteristicDao dao; - private final TechnicalDebtModelRepository languageModelFinder; - private final DebtCharacteristicsXMLImporter importer; - - public DebtModelSynchronizer(MyBatis mybatis, CharacteristicDao dao, TechnicalDebtModelRepository modelRepository, DebtCharacteristicsXMLImporter importer) { - this.mybatis = mybatis; - this.dao = dao; - this.languageModelFinder = modelRepository; - this.importer = importer; - } - - public List synchronize() { - SqlSession session = mybatis.openSession(); - - List characteristics = newArrayList(); - try { - DebtModel defaultModel = loadModelFromXml(TechnicalDebtModelRepository.DEFAULT_MODEL); - List existingCharacteristics = dao.selectEnabledCharacteristics(); - if (existingCharacteristics.isEmpty()) { - return createDebtModel(defaultModel, session); - } - } finally { - MyBatis.closeQuietly(session); - } - return characteristics; - } - - private List createDebtModel(DebtModel defaultModel, SqlSession session) { - List characteristics = newArrayList(); - for (DebtCharacteristic rootCharacteristic : defaultModel.rootCharacteristics()) { - CharacteristicDto rootCharacteristicDto = toDto(rootCharacteristic, null); - dao.insert(rootCharacteristicDto, session); - characteristics.add(rootCharacteristicDto); - for (DebtCharacteristic characteristic : defaultModel.subCharacteristics(rootCharacteristic.key())) { - CharacteristicDto characteristicDto = toDto(characteristic, rootCharacteristicDto.getId()); - dao.insert(characteristicDto, session); - characteristics.add(characteristicDto); - } - } - session.commit(); - return characteristics; - } - - private DebtModel loadModelFromXml(String pluginKey) { - Reader xmlFileReader = null; - try { - xmlFileReader = languageModelFinder.createReaderForXMLFile(pluginKey); - return importer.importXML(xmlFileReader); - } finally { - IOUtils.closeQuietly(xmlFileReader); - } - } - - private static CharacteristicDto toDto(DebtCharacteristic characteristic, @Nullable Integer parentId) { - return new CharacteristicDto() - .setKey(characteristic.key()) - .setName(characteristic.name()) - .setOrder(characteristic.order()) - .setParentId(parentId) - .setEnabled(true) - .setCreatedAt(characteristic.createdAt()) - .setUpdatedAt(characteristic.updatedAt()); - } - -} diff --git a/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index 2c8b84ed6fa..d1125b423cd 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -95,8 +95,8 @@ import org.sonar.server.notifications.NotificationService; import org.sonar.server.permission.InternalPermissionService; import org.sonar.server.permission.InternalPermissionTemplateService; import org.sonar.server.permission.PermissionFinder; -import org.sonar.server.platform.ws.SystemWs; import org.sonar.server.platform.ws.RestartHandler; +import org.sonar.server.platform.ws.SystemWs; import org.sonar.server.plugins.*; import org.sonar.server.qualitygate.QgateProjectFinder; import org.sonar.server.qualitygate.QualityGates; @@ -350,7 +350,6 @@ class ServerComponents { pico.addSingleton(DebtModelLookup.class); pico.addSingleton(DebtModelRestore.class); pico.addSingleton(TechnicalDebtModelSynchronizer.class); - pico.addSingleton(DebtModelSynchronizer.class); pico.addSingleton(TechnicalDebtModelRepository.class); pico.addSingleton(TechnicalDebtXMLImporter.class); pico.addSingleton(DebtRulesXMLImporter.class); diff --git a/sonar-server/src/main/java/org/sonar/server/startup/RegisterDebtModel.java b/sonar-server/src/main/java/org/sonar/server/startup/RegisterDebtModel.java index 59a4ecdf035..26a5c94444a 100644 --- a/sonar-server/src/main/java/org/sonar/server/startup/RegisterDebtModel.java +++ b/sonar-server/src/main/java/org/sonar/server/startup/RegisterDebtModel.java @@ -23,21 +23,26 @@ package org.sonar.server.startup; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.utils.TimeProfiler; -import org.sonar.server.debt.DebtModelSynchronizer; +import org.sonar.core.technicaldebt.db.CharacteristicDao; +import org.sonar.server.debt.DebtModelRestore; public class RegisterDebtModel { private static final Logger LOGGER = LoggerFactory.getLogger(RegisterDebtModel.class); - private final DebtModelSynchronizer manager; + private final CharacteristicDao dao; + private final DebtModelRestore debtModelRestore; - public RegisterDebtModel(DebtModelSynchronizer manager) { - this.manager = manager; + public RegisterDebtModel(CharacteristicDao dao, DebtModelRestore debtModelRestore) { + this.dao = dao; + this.debtModelRestore = debtModelRestore; } public void start() { TimeProfiler profiler = new TimeProfiler(LOGGER).start("Register technical debt model"); - manager.synchronize(); + if (dao.selectEnabledCharacteristics().isEmpty()) { + debtModelRestore.restore(); + } profiler.stop(); } diff --git a/sonar-server/src/test/java/org/sonar/server/debt/DebtModelSynchronizerTest.java b/sonar-server/src/test/java/org/sonar/server/debt/DebtModelSynchronizerTest.java deleted file mode 100644 index ca05e80d095..00000000000 --- a/sonar-server/src/test/java/org/sonar/server/debt/DebtModelSynchronizerTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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.debt; - -import com.google.common.collect.Lists; -import org.apache.ibatis.session.SqlSession; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; -import org.sonar.api.server.debt.DebtCharacteristic; -import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic; -import org.sonar.core.persistence.MyBatis; -import org.sonar.core.technicaldebt.TechnicalDebtModelRepository; -import org.sonar.core.technicaldebt.db.CharacteristicDao; -import org.sonar.core.technicaldebt.db.CharacteristicDto; - -import java.io.Reader; -import java.util.Collections; -import java.util.List; - -import static com.google.common.collect.Lists.newArrayList; -import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; - -@RunWith(MockitoJUnitRunner.class) -public class DebtModelSynchronizerTest { - - @Mock - MyBatis myBatis; - - @Mock - SqlSession session; - - @Mock - TechnicalDebtModelRepository technicalDebtModelRepository; - - @Mock - CharacteristicDao dao; - - @Mock - DebtCharacteristicsXMLImporter xmlImporter; - - Integer currentId = 1; - - DebtModel defaultModel = new DebtModel(); - - DebtModelSynchronizer manager; - - @Before - public void initAndMerge() throws Exception { - when(myBatis.openSession()).thenReturn(session); - - Reader defaultModelReader = mock(Reader.class); - when(technicalDebtModelRepository.createReaderForXMLFile("technical-debt")).thenReturn(defaultModelReader); - when(xmlImporter.importXML(eq(defaultModelReader))).thenReturn(defaultModel); - - doAnswer(new Answer() { - public Object answer(InvocationOnMock invocation) { - Object[] args = invocation.getArguments(); - CharacteristicDto dto = (CharacteristicDto) args[0]; - dto.setId(currentId++); - return null; - } - }).when(dao).insert(any(CharacteristicDto.class), any(SqlSession.class)); - - - manager = new DebtModelSynchronizer(myBatis, dao, technicalDebtModelRepository, xmlImporter); - } - - @Test - public void create_default_model_on_first_execution_when_no_plugin() throws Exception { - DebtCharacteristic characteristic = new DefaultDebtCharacteristic().setKey("PORTABILITY"); - DebtCharacteristic subCharacteristic = new DefaultDebtCharacteristic().setKey("COMPILER_RELATED_PORTABILITY"); - defaultModel.addRootCharacteristic(characteristic); - defaultModel.addSubCharacteristic(subCharacteristic, "PORTABILITY"); - - when(technicalDebtModelRepository.getContributingPluginList()).thenReturn(Collections.emptyList()); - when(dao.selectEnabledCharacteristics()).thenReturn(Lists.newArrayList()); - - manager.synchronize(); - - verify(dao).selectEnabledCharacteristics(); - ArgumentCaptor characteristicCaptor = ArgumentCaptor.forClass(CharacteristicDto.class); - verify(dao, times(2)).insert(characteristicCaptor.capture(), eq(session)); - - List result = characteristicCaptor.getAllValues(); - assertThat(result.get(0).getKey()).isEqualTo("PORTABILITY"); - assertThat(result.get(1).getKey()).isEqualTo("COMPILER_RELATED_PORTABILITY"); - verifyNoMoreInteractions(dao); - } - - @Test - public void not_create_default_model_if_already_exists() throws Exception { - DebtCharacteristic characteristic = new DefaultDebtCharacteristic().setKey("PORTABILITY"); - DebtCharacteristic subCharacteristic = new DefaultDebtCharacteristic().setKey("COMPILER_RELATED_PORTABILITY"); - defaultModel.addRootCharacteristic(characteristic); - defaultModel.addSubCharacteristic(subCharacteristic, "PORTABILITY"); - - when(technicalDebtModelRepository.getContributingPluginList()).thenReturn(Collections.emptyList()); - when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(new CharacteristicDto())); - - manager.synchronize(); - - verify(dao, never()).insert(any(CharacteristicDto.class), eq(session)); - } - -} diff --git a/sonar-server/src/test/java/org/sonar/server/startup/RegisterDebtModelTest.java b/sonar-server/src/test/java/org/sonar/server/startup/RegisterDebtModelTest.java index b6d24cbcc94..e4d207bff92 100644 --- a/sonar-server/src/test/java/org/sonar/server/startup/RegisterDebtModelTest.java +++ b/sonar-server/src/test/java/org/sonar/server/startup/RegisterDebtModelTest.java @@ -20,20 +20,51 @@ package org.sonar.server.startup; +import org.junit.Before; import org.junit.Test; -import org.sonar.server.debt.DebtModelSynchronizer; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.core.technicaldebt.db.CharacteristicDao; +import org.sonar.core.technicaldebt.db.CharacteristicDto; +import org.sonar.server.debt.DebtModelRestore; +import java.util.Collections; + +import static com.google.common.collect.Lists.newArrayList; import static org.mockito.Mockito.*; +@RunWith(MockitoJUnitRunner.class) public class RegisterDebtModelTest { + @Mock + CharacteristicDao dao; + + @Mock + DebtModelRestore debtModelRestore; + + RegisterDebtModel registerDebtModel; + + @Before + public void setUp() throws Exception { + registerDebtModel = new RegisterDebtModel(dao, debtModelRestore); + } + + @Test + public void create_debt_model() throws Exception { + when(dao.selectEnabledCharacteristics()).thenReturn(Collections.emptyList()); + + registerDebtModel.start(); + + verify(debtModelRestore).restore(); + } + @Test - public void create_model() throws Exception { - DebtModelSynchronizer synchronizer = mock(DebtModelSynchronizer.class); - RegisterDebtModel sqaleDefinition = new RegisterDebtModel(synchronizer); + public void not_create_debt_model_if_already_exists() throws Exception { + when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(new CharacteristicDto())); - sqaleDefinition.start(); + registerDebtModel.start(); - verify(synchronizer, times(1)).synchronize(); + verifyZeroInteractions(debtModelRestore); } } -- 2.39.5