From: Sébastien Lesaint Date: Thu, 21 Jun 2018 13:26:30 +0000 (+0200) Subject: move classes around to prepare creation of sonar-ce-task module X-Git-Tag: 7.5~929 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=444d5b4d5dcd12123e5b993c92bf61bdd8097872;p=sonarqube.git move classes around to prepare creation of sonar-ce-task module --- diff --git a/server/sonar-ce-task-projectanalysis/build.gradle b/server/sonar-ce-task-projectanalysis/build.gradle index 4e829cef927..5644d921ad0 100644 --- a/server/sonar-ce-task-projectanalysis/build.gradle +++ b/server/sonar-ce-task-projectanalysis/build.gradle @@ -32,7 +32,6 @@ configurations { dependencies { // please keep the list grouped by configuration and ordered by name -// compile 'org.picocontainer:picocontainer' compile 'org.slf4j:jul-to-slf4j' compile 'org.slf4j:slf4j-api' diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/ProjectAnalysisTaskModule.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/ProjectAnalysisTaskModule.java index e6252cf2743..cdaf4160067 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/ProjectAnalysisTaskModule.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/ProjectAnalysisTaskModule.java @@ -21,10 +21,8 @@ package org.sonar.ce.task.projectanalysis; import org.sonar.ce.task.projectanalysis.container.ContainerFactoryImpl; import org.sonar.ce.task.projectanalysis.taskprocessor.ReportTaskProcessor; -import org.sonar.server.computation.queue.ReportSubmitter; +import org.sonar.server.ce.queue.ReportSubmitter; import org.sonar.core.platform.Module; -import org.sonar.ce.task.projectanalysis.container.ContainerFactoryImpl; -import org.sonar.ce.task.projectanalysis.taskprocessor.ReportTaskProcessor; import org.sonar.server.computation.task.step.ComputationStepExecutor; public class ProjectAnalysisTaskModule extends Module { diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java index b25d685d67b..ceebf5dc91e 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutor.java @@ -64,7 +64,7 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor private static final Logger LOG = Loggers.get(PostProjectAnalysisTasksExecutor.class); - private final org.sonar.ce.queue.CeTask ceTask; + private final org.sonar.server.computation.CeTask ceTask; private final AnalysisMetadataHolder analysisMetadataHolder; private final QualityGateHolder qualityGateHolder; private final QualityGateStatusHolder qualityGateStatusHolder; @@ -75,18 +75,18 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor /** * Constructor used by Pico when there is no {@link PostProjectAnalysisTask} in the container. */ - public PostProjectAnalysisTasksExecutor(org.sonar.ce.queue.CeTask ceTask, - AnalysisMetadataHolder analysisMetadataHolder, - QualityGateHolder qualityGateHolder, QualityGateStatusHolder qualityGateStatusHolder, - BatchReportReader reportReader, System2 system2) { + public PostProjectAnalysisTasksExecutor(org.sonar.server.computation.CeTask ceTask, + AnalysisMetadataHolder analysisMetadataHolder, + QualityGateHolder qualityGateHolder, QualityGateStatusHolder qualityGateStatusHolder, + BatchReportReader reportReader, System2 system2) { this(ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader, system2, null); } - public PostProjectAnalysisTasksExecutor(org.sonar.ce.queue.CeTask ceTask, - AnalysisMetadataHolder analysisMetadataHolder, - QualityGateHolder qualityGateHolder, QualityGateStatusHolder qualityGateStatusHolder, - BatchReportReader reportReader, System2 system2, - @Nullable PostProjectAnalysisTask[] postProjectAnalysisTasks) { + public PostProjectAnalysisTasksExecutor(org.sonar.server.computation.CeTask ceTask, + AnalysisMetadataHolder analysisMetadataHolder, + QualityGateHolder qualityGateHolder, QualityGateStatusHolder qualityGateStatusHolder, + BatchReportReader reportReader, System2 system2, + @Nullable PostProjectAnalysisTask[] postProjectAnalysisTasks) { this.analysisMetadataHolder = analysisMetadataHolder; this.qualityGateHolder = qualityGateHolder; this.qualityGateStatusHolder = qualityGateStatusHolder; @@ -147,7 +147,7 @@ public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor } } - private static Project createProject(org.sonar.ce.queue.CeTask ceTask) { + private static Project createProject(org.sonar.server.computation.CeTask ceTask) { return new ProjectImpl( ceTask.getComponentUuid(), ceTask.getComponentKey(), diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/batch/BatchReportDirectoryHolder.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/batch/BatchReportDirectoryHolder.java index 7f4314761d3..44fd4958a83 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/batch/BatchReportDirectoryHolder.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/batch/BatchReportDirectoryHolder.java @@ -20,7 +20,7 @@ package org.sonar.ce.task.projectanalysis.batch; import java.io.File; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; public interface BatchReportDirectoryHolder { /** diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ContainerFactory.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ContainerFactory.java index b7fdb7fc19f..edfdec24ec6 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ContainerFactory.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ContainerFactory.java @@ -20,7 +20,7 @@ package org.sonar.ce.task.projectanalysis.container; import javax.annotation.Nullable; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.core.platform.ComponentContainer; import org.sonar.plugin.ce.ReportAnalysisComponentProvider; import org.sonar.server.computation.task.container.TaskContainer; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ContainerFactoryImpl.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ContainerFactoryImpl.java index b0d032a4bfb..b12e44dac98 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ContainerFactoryImpl.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ContainerFactoryImpl.java @@ -20,7 +20,7 @@ package org.sonar.ce.task.projectanalysis.container; import javax.annotation.Nullable; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.core.platform.ComponentContainer; import org.sonar.plugin.ce.ReportAnalysisComponentProvider; import org.sonar.server.computation.task.container.TaskContainer; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java index 96835c017d6..e2e143df05e 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulator.java @@ -22,9 +22,9 @@ package org.sonar.ce.task.projectanalysis.container; import java.util.Arrays; import java.util.List; import javax.annotation.Nullable; -import org.sonar.ce.organization.DefaultOrganizationLoader; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.settings.SettingsLoader; +import org.sonar.server.computation.organization.DefaultOrganizationLoader; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.settings.SettingsLoader; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderImpl; import org.sonar.ce.task.projectanalysis.api.posttask.PostProjectAnalysisTasksExecutor; import org.sonar.ce.task.projectanalysis.batch.BatchReportDirectoryHolderImpl; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCount.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCount.java index 7a5cde02d4e..ce24294946e 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCount.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCount.java @@ -21,7 +21,7 @@ package org.sonar.ce.task.projectanalysis.dbmigration; import com.google.common.collect.Iterables; import java.sql.SQLException; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.db.Database; import org.sonar.db.source.FileSourceDto; import org.sonar.server.platform.db.migration.step.DataChange; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/filemove/ScoreMatrixDumperImpl.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/filemove/ScoreMatrixDumperImpl.java index 9e0355635ff..a14629e59d0 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/filemove/ScoreMatrixDumperImpl.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/filemove/ScoreMatrixDumperImpl.java @@ -26,7 +26,7 @@ import java.nio.file.Path; import org.sonar.api.config.Configuration; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import static java.nio.charset.StandardCharsets.UTF_8; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/IndexPurgeListener.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/IndexPurgeListener.java new file mode 100644 index 00000000000..5a2ea59ae04 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/IndexPurgeListener.java @@ -0,0 +1,57 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.dbcleaner; + +import java.util.Collection; +import java.util.List; +import org.sonar.api.server.ServerSide; +import org.sonar.db.purge.PurgeListener; +import org.sonar.server.component.index.ComponentIndexer; +import org.sonar.server.issue.index.IssueIndexer; +import org.sonar.server.test.index.TestIndexer; + +@ServerSide +public class IndexPurgeListener implements PurgeListener { + private final TestIndexer testIndexer; + private final IssueIndexer issueIndexer; + private final ComponentIndexer componentIndexer; + + public IndexPurgeListener(TestIndexer testIndexer, IssueIndexer issueIndexer, ComponentIndexer componentIndexer) { + this.testIndexer = testIndexer; + this.issueIndexer = issueIndexer; + this.componentIndexer = componentIndexer; + } + + @Override + public void onComponentsDisabling(String projectUuid, Collection disabledComponentUuids) { + componentIndexer.delete(projectUuid, disabledComponentUuids); + disabledComponentUuids.forEach(this::onComponentDisabling); + } + + private void onComponentDisabling(String uuid) { + testIndexer.deleteByFile(uuid); + } + + @Override + public void onIssuesRemoval(String projectUuid, List issueKeys) { + issueIndexer.deleteByKeys(projectUuid, issueKeys); + } + +} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/ProjectCleaner.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/ProjectCleaner.java new file mode 100644 index 00000000000..63b2170ad0e --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/ProjectCleaner.java @@ -0,0 +1,79 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.dbcleaner; + +import java.util.Collection; +import org.sonar.api.CoreProperties; +import org.sonar.api.ce.ComputeEngineSide; +import org.sonar.api.config.Configuration; +import org.sonar.api.server.ServerSide; +import org.sonar.api.utils.TimeUtils; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.db.DbSession; +import org.sonar.db.purge.IdUuidPair; +import org.sonar.db.purge.PurgeConfiguration; +import org.sonar.db.purge.PurgeDao; +import org.sonar.db.purge.PurgeListener; +import org.sonar.db.purge.PurgeProfiler; +import org.sonar.db.purge.period.DefaultPeriodCleaner; + +import static org.sonar.db.purge.PurgeConfiguration.newDefaultPurgeConfiguration; + +@ServerSide +@ComputeEngineSide +public class ProjectCleaner { + private static final Logger LOG = Loggers.get(ProjectCleaner.class); + + private final PurgeProfiler profiler; + private final PurgeListener purgeListener; + private final PurgeDao purgeDao; + private final DefaultPeriodCleaner periodCleaner; + + public ProjectCleaner(PurgeDao purgeDao, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler, PurgeListener purgeListener) { + this.purgeDao = purgeDao; + this.periodCleaner = periodCleaner; + this.profiler = profiler; + this.purgeListener = purgeListener; + } + + public ProjectCleaner purge(DbSession session, IdUuidPair rootId, Configuration projectConfig, Collection disabledComponentUuids) { + long start = System.currentTimeMillis(); + profiler.reset(); + + PurgeConfiguration configuration = newDefaultPurgeConfiguration(projectConfig, rootId, disabledComponentUuids); + + periodCleaner.clean(session, configuration.rootProjectIdUuid().getUuid(), projectConfig); + purgeDao.purge(session, configuration, purgeListener, profiler); + + session.commit(); + logProfiling(start, projectConfig); + return this; + } + + private void logProfiling(long start, Configuration config) { + if (config.getBoolean(CoreProperties.PROFILING_LOG_PROPERTY).orElse(false)) { + long duration = System.currentTimeMillis() - start; + LOG.info("\n -------- Profiling for purge: " + TimeUtils.formatDuration(duration) + " --------\n"); + profiler.dump(duration, LOG); + LOG.info("\n -------- End of profiling for purge --------\n"); + } + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/PurgeDatastoresStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/PurgeDatastoresStep.java new file mode 100644 index 00000000000..380730f9eb7 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/PurgeDatastoresStep.java @@ -0,0 +1,87 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.ce.task.projectanalysis.purge; + +import org.sonar.ce.task.projectanalysis.component.Component; +import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository; +import org.sonar.ce.task.projectanalysis.component.DbIdsRepository; +import org.sonar.ce.task.projectanalysis.component.DepthTraversalTypeAwareCrawler; +import org.sonar.ce.task.projectanalysis.component.DisabledComponentsHolder; +import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; +import org.sonar.ce.task.projectanalysis.component.TypeAwareVisitorAdapter; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.purge.IdUuidPair; +import org.sonar.server.computation.dbcleaner.ProjectCleaner; +import org.sonar.server.computation.task.step.ComputationStep; + +import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT; +import static org.sonar.ce.task.projectanalysis.component.Component.Type.VIEW; +import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER; +import static org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit.reportMaxDepth; + +public class PurgeDatastoresStep implements ComputationStep { + + private final ProjectCleaner projectCleaner; + private final DbClient dbClient; + private final DbIdsRepository dbIdsRepository; + private final TreeRootHolder treeRootHolder; + private final ConfigurationRepository configRepository; + private final DisabledComponentsHolder disabledComponentsHolder; + + public PurgeDatastoresStep(DbClient dbClient, ProjectCleaner projectCleaner, DbIdsRepository dbIdsRepository, TreeRootHolder treeRootHolder, + ConfigurationRepository configRepository, DisabledComponentsHolder disabledComponentsHolder) { + this.projectCleaner = projectCleaner; + this.dbClient = dbClient; + this.dbIdsRepository = dbIdsRepository; + this.treeRootHolder = treeRootHolder; + this.configRepository = configRepository; + this.disabledComponentsHolder = disabledComponentsHolder; + } + + @Override + public void execute() { + new DepthTraversalTypeAwareCrawler( + new TypeAwareVisitorAdapter(reportMaxDepth(PROJECT).withViewsMaxDepth(VIEW), PRE_ORDER) { + @Override + public void visitProject(Component project) { + execute(project); + } + + @Override + public void visitView(Component view) { + execute(view); + } + }).visit(treeRootHolder.getRoot()); + } + + private void execute(Component root) { + try (DbSession dbSession = dbClient.openSession(true)) { + IdUuidPair idUuidPair = new IdUuidPair(dbIdsRepository.getComponentId(root), root.getUuid()); + projectCleaner.purge(dbSession, idUuidPair, configRepository.getConfiguration(), disabledComponentsHolder.getUuids()); + dbSession.commit(); + } + } + + @Override + public String getDescription() { + return "Purge db"; + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/package-info.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/package-info.java new file mode 100644 index 00000000000..c73fe5406ae --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/purge/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.dbcleaner; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ExtractReportStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ExtractReportStep.java index 6be254e1ae6..339aa1b1c96 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ExtractReportStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ExtractReportStep.java @@ -27,7 +27,7 @@ import java.util.Optional; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.TempFolder; import org.sonar.api.utils.ZipUtils; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.ce.CeTaskInputDao; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java index 9312df812d9..ace3f49bc34 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStep.java @@ -27,7 +27,7 @@ import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.lang.StringUtils; import org.sonar.api.utils.MessageException; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.ce.task.projectanalysis.component.BranchLoader; import org.sonar.core.component.ComponentKeys; import org.sonar.core.platform.PluginRepository; @@ -44,7 +44,6 @@ import org.sonar.ce.task.projectanalysis.analysis.MutableAnalysisMetadataHolder; import org.sonar.ce.task.projectanalysis.analysis.Organization; import org.sonar.ce.task.projectanalysis.analysis.ScannerPlugin; import org.sonar.ce.task.projectanalysis.batch.BatchReportReader; -import org.sonar.ce.task.projectanalysis.component.BranchLoader; import org.sonar.server.computation.task.step.ComputationStep; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.organization.OrganizationFlags; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistScannerContextStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistScannerContextStep.java index b70c23ec334..18af9f117b3 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistScannerContextStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistScannerContextStep.java @@ -19,7 +19,7 @@ */ package org.sonar.ce.task.projectanalysis.step; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.core.util.CloseableIterator; import org.sonar.db.DbClient; import org.sonar.db.DbSession; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PublishTaskResultStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PublishTaskResultStep.java index 6ab10894c89..9f009138959 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PublishTaskResultStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PublishTaskResultStep.java @@ -21,7 +21,7 @@ package org.sonar.ce.task.projectanalysis.step; import java.util.Optional; import javax.annotation.concurrent.Immutable; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTaskResult; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; import org.sonar.server.computation.task.step.ComputationStep; import org.sonar.server.computation.taskprocessor.MutableTaskResultHolder; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PurgeDatastoresStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PurgeDatastoresStep.java deleted file mode 100644 index 511f782cc93..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PurgeDatastoresStep.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.task.projectanalysis.step; - -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository; -import org.sonar.ce.task.projectanalysis.component.DbIdsRepository; -import org.sonar.ce.task.projectanalysis.component.DepthTraversalTypeAwareCrawler; -import org.sonar.ce.task.projectanalysis.component.DisabledComponentsHolder; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; -import org.sonar.ce.task.projectanalysis.component.TypeAwareVisitorAdapter; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.purge.IdUuidPair; -import org.sonar.server.computation.dbcleaner.ProjectCleaner; -import org.sonar.server.computation.task.step.ComputationStep; - -import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT; -import static org.sonar.ce.task.projectanalysis.component.Component.Type.VIEW; -import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER; -import static org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit.reportMaxDepth; - -public class PurgeDatastoresStep implements ComputationStep { - - private final ProjectCleaner projectCleaner; - private final DbClient dbClient; - private final DbIdsRepository dbIdsRepository; - private final TreeRootHolder treeRootHolder; - private final ConfigurationRepository configRepository; - private final DisabledComponentsHolder disabledComponentsHolder; - - public PurgeDatastoresStep(DbClient dbClient, ProjectCleaner projectCleaner, DbIdsRepository dbIdsRepository, TreeRootHolder treeRootHolder, - ConfigurationRepository configRepository, DisabledComponentsHolder disabledComponentsHolder) { - this.projectCleaner = projectCleaner; - this.dbClient = dbClient; - this.dbIdsRepository = dbIdsRepository; - this.treeRootHolder = treeRootHolder; - this.configRepository = configRepository; - this.disabledComponentsHolder = disabledComponentsHolder; - } - - @Override - public void execute() { - new DepthTraversalTypeAwareCrawler( - new TypeAwareVisitorAdapter(reportMaxDepth(PROJECT).withViewsMaxDepth(VIEW), PRE_ORDER) { - @Override - public void visitProject(Component project) { - execute(project); - } - - @Override - public void visitView(Component view) { - execute(view); - } - }).visit(treeRootHolder.getRoot()); - } - - private void execute(Component root) { - try (DbSession dbSession = dbClient.openSession(true)) { - IdUuidPair idUuidPair = new IdUuidPair(dbIdsRepository.getComponentId(root), root.getUuid()); - projectCleaner.purge(dbSession, idUuidPair, configRepository.getConfiguration(), disabledComponentsHolder.getUuids()); - dbSession.commit(); - } - } - - @Override - public String getDescription() { - return "Purge db"; - } -} diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java index 27c367d9e18..ed7f10a69ac 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java @@ -21,6 +21,7 @@ package org.sonar.ce.task.projectanalysis.step; import java.util.Arrays; import java.util.List; +import org.sonar.ce.task.projectanalysis.purge.PurgeDatastoresStep; import org.sonar.server.computation.task.container.TaskContainer; import org.sonar.ce.task.projectanalysis.filemove.FileMoveDetectionStep; import org.sonar.server.computation.task.step.ComputationStep; diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/ReportTaskProcessor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/ReportTaskProcessor.java index dd1f14fb43c..8ea6b797784 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/ReportTaskProcessor.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/ReportTaskProcessor.java @@ -22,8 +22,8 @@ package org.sonar.ce.task.projectanalysis.taskprocessor; import java.util.Collections; import java.util.Set; import javax.annotation.CheckForNull; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import org.sonar.ce.task.projectanalysis.container.ContainerFactory; import org.sonar.ce.taskprocessor.CeTaskProcessor; import org.sonar.core.platform.ComponentContainer; diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java index 225bf1f698b..c714a7c47ac 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/api/posttask/PostProjectAnalysisTasksExecutorTest.java @@ -38,7 +38,7 @@ import org.mockito.InOrder; import org.sonar.api.ce.posttask.PostProjectAnalysisTask; import org.sonar.api.ce.posttask.Project; import org.sonar.api.utils.System2; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule; import org.sonar.ce.task.projectanalysis.analysis.Branch; import org.sonar.ce.task.projectanalysis.analysis.Organization; diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulatorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulatorTest.java index dee5e944cbf..3ad2f042bf4 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulatorTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/container/ProjectAnalysisTaskContainerPopulatorTest.java @@ -31,7 +31,7 @@ import javax.annotation.Nullable; import org.junit.Test; import org.picocontainer.DefaultPicoContainer; import org.picocontainer.PicoContainer; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.ce.task.projectanalysis.step.PersistComponentsStep; import org.sonar.core.platform.ComponentContainer; import org.sonar.plugin.ce.ReportAnalysisComponentProvider; diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCountTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCountTest.java index 5e6a85cb16a..88f24bffb4c 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCountTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/PopulateFileSourceLineCountTest.java @@ -32,7 +32,7 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.sonar.api.utils.System2; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.db.DbTester; import org.sonar.db.source.FileSourceDto; diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/ProjectAnalysisDataChangesImplTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/ProjectAnalysisDataChangesImplTest.java index c4bab8b1656..afa25e58896 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/ProjectAnalysisDataChangesImplTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/dbmigration/ProjectAnalysisDataChangesImplTest.java @@ -24,7 +24,7 @@ import java.util.stream.Collectors; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.db.Database; import static org.assertj.core.api.Assertions.assertThat; diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/filemove/ScoreMatrixDumperImplTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/filemove/ScoreMatrixDumperImplTest.java index 9fdc10d1baa..5bbba7bf6d9 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/filemove/ScoreMatrixDumperImplTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/filemove/ScoreMatrixDumperImplTest.java @@ -35,7 +35,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.sonar.api.config.Configuration; import org.sonar.api.config.internal.MapSettings; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.ce.task.projectanalysis.filemove.ScoreMatrix.ScoreFile; import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/IndexPurgeListenerTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/IndexPurgeListenerTest.java new file mode 100644 index 00000000000..a1d8afc8ae6 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/IndexPurgeListenerTest.java @@ -0,0 +1,59 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.dbcleaner; + +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.sonar.server.component.index.ComponentIndexer; +import org.sonar.server.issue.index.IssueIndexer; +import org.sonar.server.test.index.TestIndexer; + +import static java.util.Arrays.asList; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class IndexPurgeListenerTest { + + TestIndexer testIndexer = mock(TestIndexer.class); + IssueIndexer issueIndexer = mock(IssueIndexer.class); + ComponentIndexer componentIndexer = mock(ComponentIndexer.class); + + IndexPurgeListener underTest = new IndexPurgeListener(testIndexer, issueIndexer, componentIndexer); + + @Test + public void test_onComponentDisabling() { + String uuid = "123456"; + String projectUuid = "P789"; + List uuids = Arrays.asList(uuid); + underTest.onComponentsDisabling(projectUuid, uuids); + + verify(testIndexer).deleteByFile(uuid); + verify(componentIndexer).delete(projectUuid, uuids); + } + + @Test + public void test_onIssuesRemoval() { + underTest.onIssuesRemoval("P1", asList("ISSUE1", "ISSUE2")); + + verify(issueIndexer).deleteByKeys("P1", asList("ISSUE1", "ISSUE2")); + } + +} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/ProjectCleanerTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/ProjectCleanerTest.java new file mode 100644 index 00000000000..12ae7f4eefd --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/ProjectCleanerTest.java @@ -0,0 +1,84 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.dbcleaner; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.PropertyDefinitions; +import org.sonar.api.config.internal.MapSettings; +import org.sonar.core.config.PurgeConstants; +import org.sonar.core.config.PurgeProperties; +import org.sonar.db.DbSession; +import org.sonar.db.purge.IdUuidPair; +import org.sonar.db.purge.PurgeDao; +import org.sonar.db.purge.PurgeListener; +import org.sonar.db.purge.PurgeProfiler; +import org.sonar.db.purge.period.DefaultPeriodCleaner; + +import static java.util.Collections.emptyList; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +public class ProjectCleanerTest { + + private ProjectCleaner underTest; + private PurgeDao dao = mock(PurgeDao.class); + private PurgeProfiler profiler = mock(PurgeProfiler.class); + private DefaultPeriodCleaner periodCleaner = mock(DefaultPeriodCleaner.class); + private PurgeListener purgeListener = mock(PurgeListener.class); + private MapSettings settings = new MapSettings(new PropertyDefinitions(PurgeProperties.all())); + + @Before + public void before() { + this.underTest = new ProjectCleaner(dao, periodCleaner, profiler, purgeListener); + } + + @Test + public void no_profiling_when_property_is_false() { + settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, false); + + underTest.purge(mock(DbSession.class), mock(IdUuidPair.class), settings.asConfig(), emptyList()); + + verify(profiler, never()).dump(anyLong(), any()); + } + + @Test + public void profiling_when_property_is_true() { + settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, true); + + underTest.purge(mock(DbSession.class), mock(IdUuidPair.class), settings.asConfig(), emptyList()); + + verify(profiler).dump(anyLong(), any()); + } + + @Test + public void call_period_cleaner_index_client_and_purge_dao() { + settings.setProperty(PurgeConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES, 5); + + underTest.purge(mock(DbSession.class), mock(IdUuidPair.class), settings.asConfig(), emptyList()); + + verify(periodCleaner).clean(any(), any(), any()); + verify(dao).purge(any(), any(), any(), any()); + } +} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/PurgeDatastoresStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/PurgeDatastoresStepTest.java new file mode 100644 index 00000000000..911a160e2a6 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/purge/PurgeDatastoresStepTest.java @@ -0,0 +1,158 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.ce.task.projectanalysis.purge; + +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.sonar.api.config.internal.MapSettings; +import org.sonar.ce.task.projectanalysis.component.Component; +import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository; +import org.sonar.ce.task.projectanalysis.component.MutableDbIdsRepositoryRule; +import org.sonar.ce.task.projectanalysis.component.MutableDisabledComponentsHolder; +import org.sonar.ce.task.projectanalysis.component.ReportComponent; +import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule; +import org.sonar.ce.task.projectanalysis.component.ViewsComponent; +import org.sonar.ce.task.projectanalysis.step.BaseStepTest; +import org.sonar.db.DbClient; +import org.sonar.db.purge.IdUuidPair; +import org.sonar.server.computation.dbcleaner.ProjectCleaner; +import org.sonar.server.computation.task.step.ComputationStep; +import org.sonar.server.util.WrapInSingleElementArray; + +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +@RunWith(DataProviderRunner.class) +public class PurgeDatastoresStepTest extends BaseStepTest { + + private static final String PROJECT_KEY = "PROJECT_KEY"; + private static final long PROJECT_ID = 123L; + private static final String PROJECT_UUID = "UUID-1234"; + + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); + @Rule + public MutableDbIdsRepositoryRule dbIdsRepository = MutableDbIdsRepositoryRule.standalone(); + + private ProjectCleaner projectCleaner = mock(ProjectCleaner.class); + private ConfigurationRepository settingsRepository = mock(ConfigurationRepository.class); + private MutableDisabledComponentsHolder disabledComponentsHolder = mock(MutableDisabledComponentsHolder.class, RETURNS_DEEP_STUBS); + + private PurgeDatastoresStep underTest = new PurgeDatastoresStep(mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS), projectCleaner, dbIdsRepository, treeRootHolder, + settingsRepository, disabledComponentsHolder); + + @Test + public void call_purge_method_of_the_purge_task_for_project() { + Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_UUID).setKey(PROJECT_KEY).build(); + + verify_call_purge_method_of_the_purge_task(project); + } + + @Test + public void call_purge_method_of_the_purge_task_for_view() { + Component project = ViewsComponent.builder(Component.Type.VIEW, PROJECT_KEY).setUuid(PROJECT_UUID).build(); + + verify_call_purge_method_of_the_purge_task(project); + } + + @DataProvider + public static Object[][] nonRootProjectComponentTypes() { + return dataproviderFromComponentTypeValues(new Predicate() { + @Override + public boolean apply(Component.Type input) { + return input.isReportType() && input != Component.Type.PROJECT; + } + }); + } + + @Test + @UseDataProvider("nonRootProjectComponentTypes") + public void do_not_call_purge_method_of_the_purge_task_for_other_report_components(Component.Type type) { + Component component = ReportComponent.builder(type, 1).setUuid(PROJECT_UUID).setKey(PROJECT_KEY).build(); + + verify_do_not_call_purge_method_of_the_purge_task(component); + } + + @DataProvider + public static Object[][] nonRootViewsComponentTypes() { + return dataproviderFromComponentTypeValues(new Predicate() { + @Override + public boolean apply(Component.Type input) { + return input.isViewsType() && input != Component.Type.VIEW; + } + }); + } + + @Test + @UseDataProvider("nonRootViewsComponentTypes") + public void do_not_call_purge_method_of_the_purge_task_for_other_views_components(Component.Type type) { + Component component = ViewsComponent.builder(type, PROJECT_KEY).setUuid(PROJECT_UUID).build(); + + verify_do_not_call_purge_method_of_the_purge_task(component); + } + + private void verify_do_not_call_purge_method_of_the_purge_task(Component component) { + treeRootHolder.setRoot(component); + + underTest.execute(); + + verifyNoMoreInteractions(projectCleaner); + } + + private void verify_call_purge_method_of_the_purge_task(Component project) { + treeRootHolder.setRoot(project); + when(settingsRepository.getConfiguration()).thenReturn(new MapSettings().asConfig()); + dbIdsRepository.setComponentId(project, PROJECT_ID); + + underTest.execute(); + + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(IdUuidPair.class); + verify(projectCleaner).purge(any(), argumentCaptor.capture(), any(), any()); + assertThat(argumentCaptor.getValue().getId()).isEqualTo(PROJECT_ID); + assertThat(argumentCaptor.getValue().getUuid()).isEqualTo(PROJECT_UUID); + } + + private static Object[][] dataproviderFromComponentTypeValues(Predicate predicate) { + return FluentIterable.from(asList(Component.Type.values())) + .filter(predicate) + .transform(WrapInSingleElementArray.INSTANCE) + .toArray(Object[].class); + } + + @Override + protected ComputationStep step() { + return underTest; + } + +} diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ExtractReportStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ExtractReportStepTest.java index 6c08d9cb6a7..d2b6857f196 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ExtractReportStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ExtractReportStepTest.java @@ -32,7 +32,7 @@ import org.sonar.api.utils.ZipUtils; import org.sonar.api.utils.internal.JUnitTempFolder; import org.sonar.api.utils.log.LogTester; import org.sonar.api.utils.log.LoggerLevel; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.ce.task.projectanalysis.batch.BatchReportDirectoryHolderImpl; import org.sonar.ce.task.projectanalysis.batch.MutableBatchReportDirectoryHolder; import org.sonar.db.DbTester; diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java index 95abfba20be..4a50e63a217 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadReportAnalysisMetadataHolderStepTest.java @@ -34,7 +34,7 @@ import org.junit.runner.RunWith; import org.sonar.api.Plugin; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.System2; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.ce.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule; import org.sonar.ce.task.projectanalysis.analysis.Organization; import org.sonar.ce.task.projectanalysis.analysis.ScannerPlugin; diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistScannerContextStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistScannerContextStepTest.java index 7b3ef398053..5ef9b400825 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistScannerContextStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistScannerContextStepTest.java @@ -24,7 +24,7 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.sonar.api.utils.System2; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule; import org.sonar.ce.task.projectanalysis.batch.BatchReportReaderRule; import org.sonar.core.util.CloseableIterator; diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PurgeDatastoresStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PurgeDatastoresStepTest.java deleted file mode 100644 index 5283a486253..00000000000 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PurgeDatastoresStepTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.task.projectanalysis.step; - -import com.google.common.base.Predicate; -import com.google.common.collect.FluentIterable; -import com.tngtech.java.junit.dataprovider.DataProvider; -import com.tngtech.java.junit.dataprovider.DataProviderRunner; -import com.tngtech.java.junit.dataprovider.UseDataProvider; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.sonar.api.config.internal.MapSettings; -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository; -import org.sonar.ce.task.projectanalysis.component.MutableDbIdsRepositoryRule; -import org.sonar.ce.task.projectanalysis.component.MutableDisabledComponentsHolder; -import org.sonar.ce.task.projectanalysis.component.ReportComponent; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule; -import org.sonar.ce.task.projectanalysis.component.ViewsComponent; -import org.sonar.db.DbClient; -import org.sonar.db.purge.IdUuidPair; -import org.sonar.server.computation.dbcleaner.ProjectCleaner; -import org.sonar.server.computation.task.step.ComputationStep; -import org.sonar.server.util.WrapInSingleElementArray; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.RETURNS_DEEP_STUBS; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -@RunWith(DataProviderRunner.class) -public class PurgeDatastoresStepTest extends BaseStepTest { - - private static final String PROJECT_KEY = "PROJECT_KEY"; - private static final long PROJECT_ID = 123L; - private static final String PROJECT_UUID = "UUID-1234"; - - @Rule - public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); - @Rule - public MutableDbIdsRepositoryRule dbIdsRepository = MutableDbIdsRepositoryRule.standalone(); - - private ProjectCleaner projectCleaner = mock(ProjectCleaner.class); - private ConfigurationRepository settingsRepository = mock(ConfigurationRepository.class); - private MutableDisabledComponentsHolder disabledComponentsHolder = mock(MutableDisabledComponentsHolder.class, RETURNS_DEEP_STUBS); - - private PurgeDatastoresStep underTest = new PurgeDatastoresStep(mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS), projectCleaner, dbIdsRepository, treeRootHolder, - settingsRepository, disabledComponentsHolder); - - @Test - public void call_purge_method_of_the_purge_task_for_project() { - Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_UUID).setKey(PROJECT_KEY).build(); - - verify_call_purge_method_of_the_purge_task(project); - } - - @Test - public void call_purge_method_of_the_purge_task_for_view() { - Component project = ViewsComponent.builder(Component.Type.VIEW, PROJECT_KEY).setUuid(PROJECT_UUID).build(); - - verify_call_purge_method_of_the_purge_task(project); - } - - @DataProvider - public static Object[][] nonRootProjectComponentTypes() { - return dataproviderFromComponentTypeValues(new Predicate() { - @Override - public boolean apply(Component.Type input) { - return input.isReportType() && input != Component.Type.PROJECT; - } - }); - } - - @Test - @UseDataProvider("nonRootProjectComponentTypes") - public void do_not_call_purge_method_of_the_purge_task_for_other_report_components(Component.Type type) { - Component component = ReportComponent.builder(type, 1).setUuid(PROJECT_UUID).setKey(PROJECT_KEY).build(); - - verify_do_not_call_purge_method_of_the_purge_task(component); - } - - @DataProvider - public static Object[][] nonRootViewsComponentTypes() { - return dataproviderFromComponentTypeValues(new Predicate() { - @Override - public boolean apply(Component.Type input) { - return input.isViewsType() && input != Component.Type.VIEW; - } - }); - } - - @Test - @UseDataProvider("nonRootViewsComponentTypes") - public void do_not_call_purge_method_of_the_purge_task_for_other_views_components(Component.Type type) { - Component component = ViewsComponent.builder(type, PROJECT_KEY).setUuid(PROJECT_UUID).build(); - - verify_do_not_call_purge_method_of_the_purge_task(component); - } - - private void verify_do_not_call_purge_method_of_the_purge_task(Component component) { - treeRootHolder.setRoot(component); - - underTest.execute(); - - verifyNoMoreInteractions(projectCleaner); - } - - private void verify_call_purge_method_of_the_purge_task(Component project) { - treeRootHolder.setRoot(project); - when(settingsRepository.getConfiguration()).thenReturn(new MapSettings().asConfig()); - dbIdsRepository.setComponentId(project, PROJECT_ID); - - underTest.execute(); - - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(IdUuidPair.class); - verify(projectCleaner).purge(any(), argumentCaptor.capture(), any(), any()); - assertThat(argumentCaptor.getValue().getId()).isEqualTo(PROJECT_ID); - assertThat(argumentCaptor.getValue().getUuid()).isEqualTo(PROJECT_UUID); - } - - private static Object[][] dataproviderFromComponentTypeValues(Predicate predicate) { - return FluentIterable.from(asList(Component.Type.values())) - .filter(predicate) - .transform(WrapInSingleElementArray.INSTANCE) - .toArray(Object[].class); - } - - @Override - protected ComputationStep step() { - return underTest; - } - -} diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/CeConfigurationModule.java b/server/sonar-ce/src/main/java/org/sonar/ce/CeConfigurationModule.java index c708076d72a..e2a6de90f34 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/CeConfigurationModule.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/CeConfigurationModule.java @@ -20,7 +20,7 @@ package org.sonar.ce; import org.sonar.ce.configuration.CeConfigurationImpl; -import org.sonar.ce.log.CeLogging; +import org.sonar.server.computation.log.CeTaskLogging; import org.sonar.ce.monitoring.CeDatabaseMBeanImpl; import org.sonar.core.platform.Module; import org.sonar.process.systeminfo.JvmPropertiesSection; @@ -32,7 +32,7 @@ public class CeConfigurationModule extends Module { protected void configureModule() { add( CeConfigurationImpl.class, - CeLogging.class, + CeTaskLogging.class, CeDatabaseMBeanImpl.class, new JvmStateSection("Compute Engine JVM State"), new JvmPropertiesSection("Compute Engine JVM Properties"), diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java b/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java index 387ab0fd67e..9c5cbea5aaa 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListener.java @@ -23,8 +23,8 @@ import javax.annotation.Nullable; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; import org.sonar.api.utils.System2; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import org.sonar.ce.taskprocessor.CeWorker; import org.sonar.db.DbClient; import org.sonar.db.DbSession; diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/queue/InternalCeQueue.java b/server/sonar-ce/src/main/java/org/sonar/ce/queue/InternalCeQueue.java index 1b11906750b..012ecd6dc3c 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/queue/InternalCeQueue.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/queue/InternalCeQueue.java @@ -23,6 +23,8 @@ import java.util.Optional; import java.util.Set; import javax.annotation.Nullable; import org.sonar.db.ce.CeActivityDto.Status; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; /** * Queue of pending Compute Engine tasks. Both producer and consumer actions diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/queue/InternalCeQueueImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/queue/InternalCeQueueImpl.java index 76ed4abf0a6..4117f810407 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/queue/InternalCeQueueImpl.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/queue/InternalCeQueueImpl.java @@ -40,6 +40,8 @@ import org.sonar.db.DbSession; import org.sonar.db.ce.CeActivityDto; import org.sonar.db.ce.CeQueueDao; import org.sonar.db.ce.CeQueueDto; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import org.sonar.server.computation.task.step.TypedException; import org.sonar.server.organization.DefaultOrganizationProvider; diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeLoggingWorkerExecutionListener.java b/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeLoggingWorkerExecutionListener.java index 3d7f8bb3ca5..34630cd54bd 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeLoggingWorkerExecutionListener.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeLoggingWorkerExecutionListener.java @@ -20,29 +20,29 @@ package org.sonar.ce.taskprocessor; import javax.annotation.Nullable; -import org.sonar.ce.log.CeLogging; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.log.CeTaskLogging; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import org.sonar.db.ce.CeActivityDto; /** - * {@link CeWorker.ExecutionListener} responsible of calling {@link CeLogging#initForTask(CeTask)} and - * {@link CeLogging#clearForTask()}. + * {@link CeWorker.ExecutionListener} responsible of calling {@link CeTaskLogging#initForTask(CeTask)} and + * {@link CeTaskLogging#clearForTask()}. */ public class CeLoggingWorkerExecutionListener implements CeWorker.ExecutionListener { - private final CeLogging ceLogging; + private final CeTaskLogging ceTaskLogging; - public CeLoggingWorkerExecutionListener(CeLogging ceLogging) { - this.ceLogging = ceLogging; + public CeLoggingWorkerExecutionListener(CeTaskLogging ceTaskLogging) { + this.ceTaskLogging = ceTaskLogging; } @Override public void onStart(CeTask ceTask) { - ceLogging.initForTask(ceTask); + ceTaskLogging.initForTask(ceTask); } @Override public void onEnd(CeTask ceTask, CeActivityDto.Status status, @Nullable CeTaskResult taskResult, @Nullable Throwable error) { - ceLogging.clearForTask(); + ceTaskLogging.clearForTask(); } } diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepository.java b/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepository.java index 7663c105af7..cadfd400e4e 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepository.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepository.java @@ -20,8 +20,7 @@ package org.sonar.ce.taskprocessor; import java.util.Optional; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.taskprocessor.CeTaskProcessor; +import org.sonar.server.computation.CeTask; public interface CeTaskProcessorRepository { diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryImpl.java index d4a44abd843..99e2aeb845e 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryImpl.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryImpl.java @@ -29,8 +29,7 @@ import java.util.Collection; import java.util.Map; import java.util.Optional; import javax.annotation.Nonnull; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.taskprocessor.CeTaskProcessor; +import org.sonar.server.computation.CeTask; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.FluentIterable.from; diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeWorker.java b/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeWorker.java index c7309fd5309..c257ecef19e 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeWorker.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeWorker.java @@ -22,8 +22,8 @@ package org.sonar.ce.taskprocessor; import java.util.concurrent.Callable; import javax.annotation.Nullable; import org.sonar.ce.queue.CeQueue; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import org.sonar.db.ce.CeActivityDto; /** diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeWorkerImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeWorkerImpl.java index bf308183aee..2ed412a6a12 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeWorkerImpl.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/taskprocessor/CeWorkerImpl.java @@ -28,8 +28,8 @@ import javax.annotation.Nullable; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import org.sonar.ce.queue.InternalCeQueue; import org.sonar.core.util.logs.Profiler; import org.sonar.db.ce.CeActivityDto; diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerTest.java index 749b93e7b3d..574e2fdf133 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/notification/ReportAnalysisFailureNotificationExecutionListenerTest.java @@ -29,8 +29,8 @@ import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; import org.sonar.api.notifications.Notification; import org.sonar.api.utils.System2; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import org.sonar.db.DbClient; import org.sonar.db.DbTester; import org.sonar.db.RowNotFoundException; diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/queue/InternalCeQueueImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/queue/InternalCeQueueImplTest.java index 1aab3f25bfc..15f76d2f131 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/queue/InternalCeQueueImplTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/queue/InternalCeQueueImplTest.java @@ -44,6 +44,8 @@ import org.sonar.db.ce.CeTaskTypes; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; import org.sonar.db.organization.OrganizationDto; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import org.sonar.server.computation.task.step.TypedException; import org.sonar.server.organization.DefaultOrganization; import org.sonar.server.organization.DefaultOrganizationProvider; diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeLoggingWorkerExecutionListenerTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeLoggingWorkerExecutionListenerTest.java deleted file mode 100644 index 4c2e81aaf58..00000000000 --- a/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeLoggingWorkerExecutionListenerTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.taskprocessor; - -import java.util.Random; -import org.junit.Test; -import org.mockito.Mockito; -import org.sonar.ce.log.CeLogging; -import org.sonar.ce.queue.CeTask; -import org.sonar.db.ce.CeActivityDto; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -public class CeLoggingWorkerExecutionListenerTest { - private CeLogging ceLogging = Mockito.spy(CeLogging.class); - private CeLoggingWorkerExecutionListener underTest = new CeLoggingWorkerExecutionListener(ceLogging); - - @Test - public void onStart_calls_initForTask_with_method_argument() { - CeTask ceTask = Mockito.mock(CeTask.class); - - underTest.onStart(ceTask); - - verify(ceLogging).initForTask(ceTask); - verifyNoMoreInteractions(ceLogging); - } - - @Test - public void onEnd_calls_clearForTask() { - underTest.onEnd(mock(CeTask.class), - CeActivityDto.Status.values()[new Random().nextInt(CeActivityDto.Status.values().length)], - null, null); - - verify(ceLogging).clearForTask(); - verifyNoMoreInteractions(ceLogging); - } -} diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskLoggingWorkerExecutionListenerTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskLoggingWorkerExecutionListenerTest.java new file mode 100644 index 00000000000..fc80542b72f --- /dev/null +++ b/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskLoggingWorkerExecutionListenerTest.java @@ -0,0 +1,56 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.ce.taskprocessor; + +import java.util.Random; +import org.junit.Test; +import org.mockito.Mockito; +import org.sonar.server.computation.log.CeTaskLogging; +import org.sonar.server.computation.CeTask; +import org.sonar.db.ce.CeActivityDto; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +public class CeTaskLoggingWorkerExecutionListenerTest { + private CeTaskLogging ceTaskLogging = Mockito.spy(CeTaskLogging.class); + private CeLoggingWorkerExecutionListener underTest = new CeLoggingWorkerExecutionListener(ceTaskLogging); + + @Test + public void onStart_calls_initForTask_with_method_argument() { + CeTask ceTask = Mockito.mock(CeTask.class); + + underTest.onStart(ceTask); + + verify(ceTaskLogging).initForTask(ceTask); + verifyNoMoreInteractions(ceTaskLogging); + } + + @Test + public void onEnd_calls_clearForTask() { + underTest.onEnd(mock(CeTask.class), + CeActivityDto.Status.values()[new Random().nextInt(CeActivityDto.Status.values().length)], + null, null); + + verify(ceTaskLogging).clearForTask(); + verifyNoMoreInteractions(ceTaskLogging); + } +} diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryImplTest.java index adef629f7d5..d5691e1bb08 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryImplTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryImplTest.java @@ -24,8 +24,8 @@ import java.util.Set; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import static org.assertj.core.api.Assertions.assertThat; diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryRule.java b/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryRule.java index ef548c02ff4..075c5deae31 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryRule.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeTaskProcessorRepositoryRule.java @@ -24,8 +24,8 @@ import java.util.Map; import java.util.Optional; import java.util.Set; import org.junit.rules.ExternalResource; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeWorkerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeWorkerImplTest.java index 365340a59a8..bd39488a6bf 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeWorkerImplTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/taskprocessor/CeWorkerImplTest.java @@ -35,7 +35,7 @@ import org.mockito.Mockito; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.log.LogTester; import org.sonar.api.utils.log.LoggerLevel; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.ce.queue.InternalCeQueue; import org.sonar.db.ce.CeActivityDto; import org.sonar.db.ce.CeTaskTypes; diff --git a/server/sonar-server/src/main/java/org/sonar/ce/CeModule.java b/server/sonar-server/src/main/java/org/sonar/ce/CeModule.java index f1256f01b8b..6b9e1c58a5a 100644 --- a/server/sonar-server/src/main/java/org/sonar/ce/CeModule.java +++ b/server/sonar-server/src/main/java/org/sonar/ce/CeModule.java @@ -20,16 +20,16 @@ package org.sonar.ce; import org.sonar.ce.http.CeHttpClientImpl; -import org.sonar.ce.log.CeLogging; +import org.sonar.server.computation.log.CeTaskLogging; import org.sonar.ce.queue.CeQueueImpl; import org.sonar.ce.taskprocessor.ReportTaskProcessorDeclaration; import org.sonar.core.platform.Module; -import org.sonar.server.computation.queue.ReportSubmitter; +import org.sonar.server.ce.queue.ReportSubmitter; public class CeModule extends Module { @Override protected void configureModule() { - add(CeLogging.class, + add(CeTaskLogging.class, CeHttpClientImpl.class, // Queue diff --git a/server/sonar-server/src/main/java/org/sonar/ce/log/CeLogging.java b/server/sonar-server/src/main/java/org/sonar/ce/log/CeLogging.java deleted file mode 100644 index b6569cdaf91..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/ce/log/CeLogging.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.log; - -import org.slf4j.MDC; -import org.sonar.ce.queue.CeTask; - -public class CeLogging { - - static final String MDC_CE_TASK_UUID = "ceTaskUuid"; - - public void initForTask(CeTask task) { - MDC.put(MDC_CE_TASK_UUID, task.getUuid()); - } - - public void clearForTask() { - MDC.remove(MDC_CE_TASK_UUID); - } - -} diff --git a/server/sonar-server/src/main/java/org/sonar/ce/log/CeProcessLogging.java b/server/sonar-server/src/main/java/org/sonar/ce/log/CeProcessLogging.java index aba706cadc5..0779ba4c04c 100644 --- a/server/sonar-server/src/main/java/org/sonar/ce/log/CeProcessLogging.java +++ b/server/sonar-server/src/main/java/org/sonar/ce/log/CeProcessLogging.java @@ -25,7 +25,7 @@ import org.sonar.process.logging.LogDomain; import org.sonar.process.logging.LogLevelConfig; import org.sonar.server.app.ServerProcessLogging; -import static org.sonar.ce.log.CeLogging.MDC_CE_TASK_UUID; +import static org.sonar.server.computation.log.CeTaskLogging.MDC_CE_TASK_UUID; /** * Configure logback for the Compute Engine process. Logs are written to file "ce.log" in SQ's log directory. diff --git a/server/sonar-server/src/main/java/org/sonar/ce/organization/DefaultOrganizationLoader.java b/server/sonar-server/src/main/java/org/sonar/ce/organization/DefaultOrganizationLoader.java deleted file mode 100644 index fc107196ca9..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/ce/organization/DefaultOrganizationLoader.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.organization; - -import org.picocontainer.Startable; -import org.sonar.api.ce.ComputeEngineSide; -import org.sonar.server.computation.task.container.EagerStart; -import org.sonar.server.organization.DefaultOrganizationCache; - -@EagerStart -@ComputeEngineSide -public class DefaultOrganizationLoader implements Startable { - private final DefaultOrganizationCache defaultOrganizationCache; - - public DefaultOrganizationLoader(DefaultOrganizationCache defaultOrganizationCache) { - this.defaultOrganizationCache = defaultOrganizationCache; - } - - @Override - public void start() { - defaultOrganizationCache.load(); - } - - @Override - public void stop() { - defaultOrganizationCache.unload(); - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/ce/organization/package-info.java b/server/sonar-server/src/main/java/org/sonar/ce/organization/package-info.java deleted file mode 100644 index 126c08b7ffa..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/ce/organization/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.organization; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/ce/queue/CeQueue.java b/server/sonar-server/src/main/java/org/sonar/ce/queue/CeQueue.java index b4982b9e41d..86cff2af7bf 100644 --- a/server/sonar-server/src/main/java/org/sonar/ce/queue/CeQueue.java +++ b/server/sonar-server/src/main/java/org/sonar/ce/queue/CeQueue.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Optional; import org.sonar.db.DbSession; import org.sonar.db.ce.CeQueueDto; +import org.sonar.server.computation.CeTask; /** * Queue of pending Compute Engine tasks. Both producer and consumer actions diff --git a/server/sonar-server/src/main/java/org/sonar/ce/queue/CeQueueImpl.java b/server/sonar-server/src/main/java/org/sonar/ce/queue/CeQueueImpl.java index c7966317717..3b8dd3832c4 100644 --- a/server/sonar-server/src/main/java/org/sonar/ce/queue/CeQueueImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/ce/queue/CeQueueImpl.java @@ -41,6 +41,7 @@ import org.sonar.db.DbSession; import org.sonar.db.ce.CeActivityDto; import org.sonar.db.ce.CeQueueDto; import org.sonar.db.component.ComponentDto; +import org.sonar.server.computation.CeTask; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.property.InternalProperties; diff --git a/server/sonar-server/src/main/java/org/sonar/ce/queue/CeTask.java b/server/sonar-server/src/main/java/org/sonar/ce/queue/CeTask.java deleted file mode 100644 index 008972bbbc9..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/ce/queue/CeTask.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.queue; - -import com.google.common.base.MoreObjects; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; - -import static com.google.common.base.Strings.emptyToNull; -import static java.util.Objects.requireNonNull; - -@Immutable -public class CeTask { - - private final String organizationUuid; - private final String type; - private final String uuid; - private final String componentUuid; - private final String componentKey; - private final String componentName; - private final String submitterUuid; - - private CeTask(Builder builder) { - this.organizationUuid = requireNonNull(emptyToNull(builder.organizationUuid), "organizationUuid can't be null nor empty"); - this.uuid = requireNonNull(emptyToNull(builder.uuid), "uuid can't be null nor empty"); - this.type = requireNonNull(emptyToNull(builder.type), "type can't be null nor empty"); - this.componentUuid = emptyToNull(builder.componentUuid); - this.componentKey = emptyToNull(builder.componentKey); - this.componentName = emptyToNull(builder.componentName); - this.submitterUuid = emptyToNull(builder.submitterUuid); - } - - public String getOrganizationUuid() { - return organizationUuid; - } - - public String getUuid() { - return uuid; - } - - public String getType() { - return type; - } - - @CheckForNull - public String getComponentUuid() { - return componentUuid; - } - - @CheckForNull - public String getComponentKey() { - return componentKey; - } - - @CheckForNull - public String getComponentName() { - return componentName; - } - - @CheckForNull - public String getSubmitterUuid() { - return submitterUuid; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("organizationUuid", organizationUuid) - .add("type", type) - .add("uuid", uuid) - .add("componentUuid", componentUuid) - .add("componentKey", componentKey) - .add("componentName", componentName) - .add("submitterUuid", submitterUuid) - .toString(); - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - CeTask ceTask = (CeTask) o; - return uuid.equals(ceTask.uuid); - } - - @Override - public int hashCode() { - return uuid.hashCode(); - } - - public static final class Builder { - private String organizationUuid; - private String uuid; - private String type; - private String componentUuid; - private String componentKey; - private String componentName; - private String submitterUuid; - - public Builder setOrganizationUuid(String organizationUuid) { - this.organizationUuid = organizationUuid; - return this; - } - - // FIXME remove this method when organization support is added to the Compute Engine queue - public boolean hasOrganizationUuid() { - return organizationUuid != null; - } - - public Builder setUuid(String uuid) { - this.uuid = uuid; - return this; - } - - public Builder setType(String type) { - this.type = type; - return this; - } - - public Builder setComponentUuid(String componentUuid) { - this.componentUuid = componentUuid; - return this; - } - - public Builder setComponentKey(@Nullable String s) { - this.componentKey = s; - return this; - } - - public Builder setComponentName(@Nullable String s) { - this.componentName = s; - return this; - } - - public Builder setSubmitterUuid(@Nullable String s) { - this.submitterUuid = s; - return this; - } - - public CeTask build() { - return new CeTask(this); - } - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/ce/queue/CeTaskResult.java b/server/sonar-server/src/main/java/org/sonar/ce/queue/CeTaskResult.java deleted file mode 100644 index cb4b485f29a..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/ce/queue/CeTaskResult.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.queue; - -import java.util.Optional; -import org.sonar.ce.taskprocessor.CeTaskProcessor; - -/** - * Represents the result of the processing of a {@link CeTask}. - * - * @see {@link CeTaskProcessor#process(CeTask)} - */ -@FunctionalInterface -public interface CeTaskResult { - /** - * The UUID of the analysis created, if any, for the Component in {@link CeTask} - */ - Optional getAnalysisUuid(); -} diff --git a/server/sonar-server/src/main/java/org/sonar/ce/settings/SettingsLoader.java b/server/sonar-server/src/main/java/org/sonar/ce/settings/SettingsLoader.java deleted file mode 100644 index 6fbfe71a206..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/ce/settings/SettingsLoader.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.settings; - -import org.picocontainer.Startable; -import org.sonar.api.ce.ComputeEngineSide; -import org.sonar.server.computation.task.container.EagerStart; -import org.sonar.server.computation.task.container.TaskContainerImpl; -import org.sonar.server.setting.ThreadLocalSettings; - -/** - * Add this class as the first components in the {@link TaskContainerImpl} - * to trigger loading of Thread local specific {@link org.sonar.api.config.Settings} in {@link ThreadLocalSettings}. - */ -@EagerStart -@ComputeEngineSide -public class SettingsLoader implements Startable { - private final ThreadLocalSettings threadLocalSettings; - - public SettingsLoader(ThreadLocalSettings threadLocalSettings) { - this.threadLocalSettings = threadLocalSettings; - } - - @Override - public void start() { - threadLocalSettings.load(); - } - - @Override - public void stop() { - threadLocalSettings.unload(); - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/ce/settings/package-info.java b/server/sonar-server/src/main/java/org/sonar/ce/settings/package-info.java deleted file mode 100644 index 3fe1981783e..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/ce/settings/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.settings; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessor.java b/server/sonar-server/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessor.java index f7378ad2adc..215a97aaa0a 100644 --- a/server/sonar-server/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessor.java +++ b/server/sonar-server/src/main/java/org/sonar/ce/taskprocessor/CeTaskProcessor.java @@ -23,8 +23,8 @@ import java.util.Set; import javax.annotation.CheckForNull; import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.server.ServerSide; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; /** * This interface is used to provide the processing code for {@link CeTask}s of one or more type to be called by the diff --git a/server/sonar-server/src/main/java/org/sonar/ce/taskprocessor/ReportTaskProcessorDeclaration.java b/server/sonar-server/src/main/java/org/sonar/ce/taskprocessor/ReportTaskProcessorDeclaration.java index 8c14ac2a97f..d25b24d865f 100644 --- a/server/sonar-server/src/main/java/org/sonar/ce/taskprocessor/ReportTaskProcessorDeclaration.java +++ b/server/sonar-server/src/main/java/org/sonar/ce/taskprocessor/ReportTaskProcessorDeclaration.java @@ -21,8 +21,8 @@ package org.sonar.ce.taskprocessor; import java.util.Collections; import java.util.Set; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import org.sonar.db.ce.CeTaskTypes; /** diff --git a/server/sonar-server/src/main/java/org/sonar/server/ce/queue/ReportSubmitter.java b/server/sonar-server/src/main/java/org/sonar/server/ce/queue/ReportSubmitter.java new file mode 100644 index 00000000000..bee5e24269b --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/ce/queue/ReportSubmitter.java @@ -0,0 +1,198 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.ce.queue; + +import com.google.common.base.Optional; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Scopes; +import org.sonar.api.server.ServerSide; +import org.sonar.ce.queue.CeQueue; +import org.sonar.server.computation.CeTask; +import org.sonar.ce.queue.CeTaskSubmit; +import org.sonar.core.component.ComponentKeys; +import org.sonar.core.util.UuidFactory; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.ce.CeTaskCharacteristicDto; +import org.sonar.db.ce.CeTaskTypes; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.permission.OrganizationPermission; +import org.sonar.server.component.ComponentUpdater; +import org.sonar.server.component.NewComponent; +import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.permission.PermissionTemplateService; +import org.sonar.server.user.UserSession; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.lang.String.format; +import static org.apache.commons.lang.StringUtils.defaultIfBlank; +import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; +import static org.sonar.server.component.NewComponent.newComponentBuilder; +import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; + +@ServerSide +public class ReportSubmitter { + + private final CeQueue queue; + private final UserSession userSession; + private final ComponentUpdater componentUpdater; + private final PermissionTemplateService permissionTemplateService; + private final DbClient dbClient; + private final UuidFactory uuidFactory; + + public ReportSubmitter(CeQueue queue, UserSession userSession, ComponentUpdater componentUpdater, + PermissionTemplateService permissionTemplateService, UuidFactory uuidFactory, DbClient dbClient) { + this.queue = queue; + this.userSession = userSession; + this.componentUpdater = componentUpdater; + this.permissionTemplateService = permissionTemplateService; + this.uuidFactory = uuidFactory; + this.dbClient = dbClient; + } + + public CeTask submit(String organizationKey, String projectKey, @Nullable String projectBranch, @Nullable String projectName, InputStream reportInput) { + return submit(organizationKey, projectKey, projectBranch, projectName, Collections.emptyMap(), reportInput); + } + + /** + * @throws NotFoundException if the organization with the specified key does not exist + * @throws IllegalArgumentException if the organization with the specified key is not the organization of the specified project (when it already exists in DB) + */ + public CeTask submit(String organizationKey, String projectKey, @Nullable String projectBranch, @Nullable String projectName, Map characteristics, + InputStream reportInput) { + try (DbSession dbSession = dbClient.openSession(false)) { + OrganizationDto organizationDto = getOrganizationDtoOrFail(dbSession, organizationKey); + String effectiveProjectKey = ComponentKeys.createKey(projectKey, projectBranch); + Optional component = dbClient.componentDao().selectByKey(dbSession, effectiveProjectKey); + validateProject(dbSession, component, projectKey); + ensureOrganizationIsConsistent(component, organizationDto); + ComponentDto project = component.or(() -> createProject(dbSession, organizationDto, projectKey, projectBranch, projectName)); + checkScanPermission(project); + return submitReport(dbSession, reportInput, project, characteristics); + } + } + + private void checkScanPermission(ComponentDto project) { + // this is a specific and inconsistent behavior. For legacy reasons, "technical users" + // defined on an organization should be able to analyze a project even if + // they don't have the direct permission on the project. + // That means that dropping the permission on the project does not have any effects + // if user has still the permission on the organization + if (!userSession.hasComponentPermission(SCAN_EXECUTION, project) && + !userSession.hasPermission(OrganizationPermission.SCAN, project.getOrganizationUuid())) { + throw insufficientPrivilegesException(); + } + } + + private OrganizationDto getOrganizationDtoOrFail(DbSession dbSession, String organizationKey) { + return dbClient.organizationDao().selectByKey(dbSession, organizationKey) + .orElseThrow(() -> new NotFoundException(format("Organization with key '%s' does not exist", organizationKey))); + } + + private void validateProject(DbSession dbSession, Optional project, String rawProjectKey) { + List errors = new ArrayList<>(); + if (!project.isPresent()) { + return; + } + + ComponentDto component = project.get(); + if (!Qualifiers.PROJECT.equals(component.qualifier()) || !Scopes.PROJECT.equals(component.scope())) { + errors.add(format("Component '%s' is not a project", rawProjectKey)); + } + if (!component.projectUuid().equals(component.uuid())) { + // Project key is already used as a module of another project + ComponentDto anotherBaseProject = dbClient.componentDao().selectOrFailByUuid(dbSession, component.projectUuid()); + errors.add(format("The project '%s' is already defined in SonarQube but as a module of project '%s'. " + + "If you really want to stop directly analysing project '%s', please first delete it from SonarQube and then relaunch the analysis of project '%s'.", + rawProjectKey, anotherBaseProject.getKey(), anotherBaseProject.getKey(), rawProjectKey)); + } + if (!errors.isEmpty()) { + throw BadRequestException.create(errors); + } + } + + private static void ensureOrganizationIsConsistent(Optional project, OrganizationDto organizationDto) { + if (project.isPresent()) { + checkArgument(project.get().getOrganizationUuid().equals(organizationDto.getUuid()), + "Organization of component with key '%s' does not match specified organization '%s'", + project.get().getDbKey(), organizationDto.getKey()); + } + } + + private ComponentDto createProject(DbSession dbSession, OrganizationDto organization, String projectKey, @Nullable String deprecatedBranch, @Nullable String projectName) { + userSession.checkPermission(OrganizationPermission.PROVISION_PROJECTS, organization); + Integer userId = userSession.getUserId(); + + String effectiveProjectKey = ComponentKeys.createEffectiveKey(projectKey, deprecatedBranch); + boolean wouldCurrentUserHaveScanPermission = permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate( + dbSession, organization.getUuid(), userId, effectiveProjectKey, Qualifiers.PROJECT); + if (!wouldCurrentUserHaveScanPermission) { + throw insufficientPrivilegesException(); + } + + boolean newProjectPrivate = dbClient.organizationDao().getNewProjectPrivate(dbSession, organization); + + NewComponent newProject = newComponentBuilder() + .setOrganizationUuid(organization.getUuid()) + .setKey(projectKey) + .setName(defaultIfBlank(projectName, projectKey)) + .setBranch(deprecatedBranch) + .setQualifier(Qualifiers.PROJECT) + .setPrivate(newProjectPrivate) + .build(); + return componentUpdater.create(dbSession, newProject, userId); + } + + private CeTask submitReport(DbSession dbSession, InputStream reportInput, ComponentDto project, Map characteristicsMap) { + CeTaskSubmit.Builder submit = queue.prepareSubmit(); + List characteristics = characteristicsMap.entrySet().stream() + .map(e -> toDto(submit.getUuid(), e.getKey(), e.getValue())).collect(Collectors.toList()); + + // the report file must be saved before submitting the task + dbClient.ceTaskInputDao().insert(dbSession, submit.getUuid(), reportInput); + if (!characteristics.isEmpty()) { + dbClient.ceTaskCharacteristicsDao().insert(dbSession, characteristics); + } + dbSession.commit(); + + submit.setType(CeTaskTypes.REPORT); + submit.setComponentUuid(project.uuid()); + submit.setSubmitterUuid(userSession.getUuid()); + return queue.submit(submit.build()); + } + + private CeTaskCharacteristicDto toDto(String taskUuid, String key, String value) { + CeTaskCharacteristicDto dto = new CeTaskCharacteristicDto(); + dto.setTaskUuid(taskUuid); + dto.setKey(key); + dto.setValue(value); + dto.setUuid(uuidFactory.create()); + return dto; + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/ce/queue/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/ce/queue/package-info.java new file mode 100644 index 00000000000..33274785b6a --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/ce/queue/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.ce.queue; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/SubmitAction.java b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/SubmitAction.java index 102565e3b14..e869d82cc8c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/SubmitAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/SubmitAction.java @@ -27,8 +27,8 @@ import org.apache.commons.lang.StringUtils; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.ce.queue.CeTask; -import org.sonar.server.computation.queue.ReportSubmitter; +import org.sonar.server.computation.CeTask; +import org.sonar.server.ce.queue.ReportSubmitter; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.ws.WsUtils; import org.sonarqube.ws.Ce; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/CeTask.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CeTask.java new file mode 100644 index 00000000000..f0d4f06ddcf --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/CeTask.java @@ -0,0 +1,166 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation; + +import com.google.common.base.MoreObjects; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +import static com.google.common.base.Strings.emptyToNull; +import static java.util.Objects.requireNonNull; + +@Immutable +public class CeTask { + + private final String organizationUuid; + private final String type; + private final String uuid; + private final String componentUuid; + private final String componentKey; + private final String componentName; + private final String submitterUuid; + + private CeTask(Builder builder) { + this.organizationUuid = requireNonNull(emptyToNull(builder.organizationUuid), "organizationUuid can't be null nor empty"); + this.uuid = requireNonNull(emptyToNull(builder.uuid), "uuid can't be null nor empty"); + this.type = requireNonNull(emptyToNull(builder.type), "type can't be null nor empty"); + this.componentUuid = emptyToNull(builder.componentUuid); + this.componentKey = emptyToNull(builder.componentKey); + this.componentName = emptyToNull(builder.componentName); + this.submitterUuid = emptyToNull(builder.submitterUuid); + } + + public String getOrganizationUuid() { + return organizationUuid; + } + + public String getUuid() { + return uuid; + } + + public String getType() { + return type; + } + + @CheckForNull + public String getComponentUuid() { + return componentUuid; + } + + @CheckForNull + public String getComponentKey() { + return componentKey; + } + + @CheckForNull + public String getComponentName() { + return componentName; + } + + @CheckForNull + public String getSubmitterUuid() { + return submitterUuid; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("organizationUuid", organizationUuid) + .add("type", type) + .add("uuid", uuid) + .add("componentUuid", componentUuid) + .add("componentKey", componentKey) + .add("componentName", componentName) + .add("submitterUuid", submitterUuid) + .toString(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CeTask ceTask = (CeTask) o; + return uuid.equals(ceTask.uuid); + } + + @Override + public int hashCode() { + return uuid.hashCode(); + } + + public static final class Builder { + private String organizationUuid; + private String uuid; + private String type; + private String componentUuid; + private String componentKey; + private String componentName; + private String submitterUuid; + + public Builder setOrganizationUuid(String organizationUuid) { + this.organizationUuid = organizationUuid; + return this; + } + + // FIXME remove this method when organization support is added to the Compute Engine queue + public boolean hasOrganizationUuid() { + return organizationUuid != null; + } + + public Builder setUuid(String uuid) { + this.uuid = uuid; + return this; + } + + public Builder setType(String type) { + this.type = type; + return this; + } + + public Builder setComponentUuid(String componentUuid) { + this.componentUuid = componentUuid; + return this; + } + + public Builder setComponentKey(@Nullable String s) { + this.componentKey = s; + return this; + } + + public Builder setComponentName(@Nullable String s) { + this.componentName = s; + return this; + } + + public Builder setSubmitterUuid(@Nullable String s) { + this.submitterUuid = s; + return this; + } + + public CeTask build() { + return new CeTask(this); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/CeTaskResult.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CeTaskResult.java new file mode 100644 index 00000000000..73dcb927513 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/CeTaskResult.java @@ -0,0 +1,33 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation; + +import java.util.Optional; + +/** + * Represents the result of the processing of a {@link CeTask}. + */ +@FunctionalInterface +public interface CeTaskResult { + /** + * The UUID of the analysis created, if any, for the Component in {@link CeTask} + */ + Optional getAnalysisUuid(); +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/IndexPurgeListener.java b/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/IndexPurgeListener.java deleted file mode 100644 index 5a2ea59ae04..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/IndexPurgeListener.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.dbcleaner; - -import java.util.Collection; -import java.util.List; -import org.sonar.api.server.ServerSide; -import org.sonar.db.purge.PurgeListener; -import org.sonar.server.component.index.ComponentIndexer; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.test.index.TestIndexer; - -@ServerSide -public class IndexPurgeListener implements PurgeListener { - private final TestIndexer testIndexer; - private final IssueIndexer issueIndexer; - private final ComponentIndexer componentIndexer; - - public IndexPurgeListener(TestIndexer testIndexer, IssueIndexer issueIndexer, ComponentIndexer componentIndexer) { - this.testIndexer = testIndexer; - this.issueIndexer = issueIndexer; - this.componentIndexer = componentIndexer; - } - - @Override - public void onComponentsDisabling(String projectUuid, Collection disabledComponentUuids) { - componentIndexer.delete(projectUuid, disabledComponentUuids); - disabledComponentUuids.forEach(this::onComponentDisabling); - } - - private void onComponentDisabling(String uuid) { - testIndexer.deleteByFile(uuid); - } - - @Override - public void onIssuesRemoval(String projectUuid, List issueKeys) { - issueIndexer.deleteByKeys(projectUuid, issueKeys); - } - -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectCleaner.java b/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectCleaner.java deleted file mode 100644 index 63b2170ad0e..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/ProjectCleaner.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.dbcleaner; - -import java.util.Collection; -import org.sonar.api.CoreProperties; -import org.sonar.api.ce.ComputeEngineSide; -import org.sonar.api.config.Configuration; -import org.sonar.api.server.ServerSide; -import org.sonar.api.utils.TimeUtils; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.db.DbSession; -import org.sonar.db.purge.IdUuidPair; -import org.sonar.db.purge.PurgeConfiguration; -import org.sonar.db.purge.PurgeDao; -import org.sonar.db.purge.PurgeListener; -import org.sonar.db.purge.PurgeProfiler; -import org.sonar.db.purge.period.DefaultPeriodCleaner; - -import static org.sonar.db.purge.PurgeConfiguration.newDefaultPurgeConfiguration; - -@ServerSide -@ComputeEngineSide -public class ProjectCleaner { - private static final Logger LOG = Loggers.get(ProjectCleaner.class); - - private final PurgeProfiler profiler; - private final PurgeListener purgeListener; - private final PurgeDao purgeDao; - private final DefaultPeriodCleaner periodCleaner; - - public ProjectCleaner(PurgeDao purgeDao, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler, PurgeListener purgeListener) { - this.purgeDao = purgeDao; - this.periodCleaner = periodCleaner; - this.profiler = profiler; - this.purgeListener = purgeListener; - } - - public ProjectCleaner purge(DbSession session, IdUuidPair rootId, Configuration projectConfig, Collection disabledComponentUuids) { - long start = System.currentTimeMillis(); - profiler.reset(); - - PurgeConfiguration configuration = newDefaultPurgeConfiguration(projectConfig, rootId, disabledComponentUuids); - - periodCleaner.clean(session, configuration.rootProjectIdUuid().getUuid(), projectConfig); - purgeDao.purge(session, configuration, purgeListener, profiler); - - session.commit(); - logProfiling(start, projectConfig); - return this; - } - - private void logProfiling(long start, Configuration config) { - if (config.getBoolean(CoreProperties.PROFILING_LOG_PROPERTY).orElse(false)) { - long duration = System.currentTimeMillis() - start; - LOG.info("\n -------- Profiling for purge: " + TimeUtils.formatDuration(duration) + " --------\n"); - profiler.dump(duration, LOG); - LOG.info("\n -------- End of profiling for purge --------\n"); - } - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/package-info.java deleted file mode 100644 index c73fe5406ae..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/dbcleaner/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.dbcleaner; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/log/CeTaskLogging.java b/server/sonar-server/src/main/java/org/sonar/server/computation/log/CeTaskLogging.java new file mode 100644 index 00000000000..8f1dbba3ced --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/log/CeTaskLogging.java @@ -0,0 +1,37 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.log; + +import org.slf4j.MDC; +import org.sonar.server.computation.CeTask; + +public class CeTaskLogging { + + public static final String MDC_CE_TASK_UUID = "ceTaskUuid"; + + public void initForTask(CeTask task) { + MDC.put(MDC_CE_TASK_UUID, task.getUuid()); + } + + public void clearForTask() { + MDC.remove(MDC_CE_TASK_UUID); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/log/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/log/package-info.java new file mode 100644 index 00000000000..1088bac9be7 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/log/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.log; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/organization/DefaultOrganizationLoader.java b/server/sonar-server/src/main/java/org/sonar/server/computation/organization/DefaultOrganizationLoader.java new file mode 100644 index 00000000000..8c36d2227a3 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/organization/DefaultOrganizationLoader.java @@ -0,0 +1,45 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.organization; + +import org.picocontainer.Startable; +import org.sonar.api.ce.ComputeEngineSide; +import org.sonar.server.computation.task.container.EagerStart; +import org.sonar.server.organization.DefaultOrganizationCache; + +@EagerStart +@ComputeEngineSide +public class DefaultOrganizationLoader implements Startable { + private final DefaultOrganizationCache defaultOrganizationCache; + + public DefaultOrganizationLoader(DefaultOrganizationCache defaultOrganizationCache) { + this.defaultOrganizationCache = defaultOrganizationCache; + } + + @Override + public void start() { + defaultOrganizationCache.load(); + } + + @Override + public void stop() { + defaultOrganizationCache.unload(); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/organization/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/organization/package-info.java new file mode 100644 index 00000000000..8e76145cb54 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/organization/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.organization; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java deleted file mode 100644 index 728124dfab6..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/ReportSubmitter.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.queue; - -import com.google.common.base.Optional; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import javax.annotation.Nullable; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Scopes; -import org.sonar.api.server.ServerSide; -import org.sonar.ce.queue.CeQueue; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskSubmit; -import org.sonar.core.component.ComponentKeys; -import org.sonar.core.util.UuidFactory; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.ce.CeTaskCharacteristicDto; -import org.sonar.db.ce.CeTaskTypes; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.permission.OrganizationPermission; -import org.sonar.server.component.ComponentUpdater; -import org.sonar.server.component.NewComponent; -import org.sonar.server.exceptions.BadRequestException; -import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.permission.PermissionTemplateService; -import org.sonar.server.user.UserSession; - -import static com.google.common.base.Preconditions.checkArgument; -import static java.lang.String.format; -import static org.apache.commons.lang.StringUtils.defaultIfBlank; -import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; -import static org.sonar.server.component.NewComponent.newComponentBuilder; -import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; - -@ServerSide -public class ReportSubmitter { - - private final CeQueue queue; - private final UserSession userSession; - private final ComponentUpdater componentUpdater; - private final PermissionTemplateService permissionTemplateService; - private final DbClient dbClient; - private final UuidFactory uuidFactory; - - public ReportSubmitter(CeQueue queue, UserSession userSession, ComponentUpdater componentUpdater, - PermissionTemplateService permissionTemplateService, UuidFactory uuidFactory, DbClient dbClient) { - this.queue = queue; - this.userSession = userSession; - this.componentUpdater = componentUpdater; - this.permissionTemplateService = permissionTemplateService; - this.uuidFactory = uuidFactory; - this.dbClient = dbClient; - } - - public CeTask submit(String organizationKey, String projectKey, @Nullable String projectBranch, @Nullable String projectName, InputStream reportInput) { - return submit(organizationKey, projectKey, projectBranch, projectName, Collections.emptyMap(), reportInput); - } - - /** - * @throws NotFoundException if the organization with the specified key does not exist - * @throws IllegalArgumentException if the organization with the specified key is not the organization of the specified project (when it already exists in DB) - */ - public CeTask submit(String organizationKey, String projectKey, @Nullable String projectBranch, @Nullable String projectName, Map characteristics, - InputStream reportInput) { - try (DbSession dbSession = dbClient.openSession(false)) { - OrganizationDto organizationDto = getOrganizationDtoOrFail(dbSession, organizationKey); - String effectiveProjectKey = ComponentKeys.createKey(projectKey, projectBranch); - Optional component = dbClient.componentDao().selectByKey(dbSession, effectiveProjectKey); - validateProject(dbSession, component, projectKey); - ensureOrganizationIsConsistent(component, organizationDto); - ComponentDto project = component.or(() -> createProject(dbSession, organizationDto, projectKey, projectBranch, projectName)); - checkScanPermission(project); - return submitReport(dbSession, reportInput, project, characteristics); - } - } - - private void checkScanPermission(ComponentDto project) { - // this is a specific and inconsistent behavior. For legacy reasons, "technical users" - // defined on an organization should be able to analyze a project even if - // they don't have the direct permission on the project. - // That means that dropping the permission on the project does not have any effects - // if user has still the permission on the organization - if (!userSession.hasComponentPermission(SCAN_EXECUTION, project) && - !userSession.hasPermission(OrganizationPermission.SCAN, project.getOrganizationUuid())) { - throw insufficientPrivilegesException(); - } - } - - private OrganizationDto getOrganizationDtoOrFail(DbSession dbSession, String organizationKey) { - return dbClient.organizationDao().selectByKey(dbSession, organizationKey) - .orElseThrow(() -> new NotFoundException(format("Organization with key '%s' does not exist", organizationKey))); - } - - private void validateProject(DbSession dbSession, Optional project, String rawProjectKey) { - List errors = new ArrayList<>(); - if (!project.isPresent()) { - return; - } - - ComponentDto component = project.get(); - if (!Qualifiers.PROJECT.equals(component.qualifier()) || !Scopes.PROJECT.equals(component.scope())) { - errors.add(format("Component '%s' is not a project", rawProjectKey)); - } - if (!component.projectUuid().equals(component.uuid())) { - // Project key is already used as a module of another project - ComponentDto anotherBaseProject = dbClient.componentDao().selectOrFailByUuid(dbSession, component.projectUuid()); - errors.add(format("The project '%s' is already defined in SonarQube but as a module of project '%s'. " - + "If you really want to stop directly analysing project '%s', please first delete it from SonarQube and then relaunch the analysis of project '%s'.", - rawProjectKey, anotherBaseProject.getKey(), anotherBaseProject.getKey(), rawProjectKey)); - } - if (!errors.isEmpty()) { - throw BadRequestException.create(errors); - } - } - - private static void ensureOrganizationIsConsistent(Optional project, OrganizationDto organizationDto) { - if (project.isPresent()) { - checkArgument(project.get().getOrganizationUuid().equals(organizationDto.getUuid()), - "Organization of component with key '%s' does not match specified organization '%s'", - project.get().getDbKey(), organizationDto.getKey()); - } - } - - private ComponentDto createProject(DbSession dbSession, OrganizationDto organization, String projectKey, @Nullable String deprecatedBranch, @Nullable String projectName) { - userSession.checkPermission(OrganizationPermission.PROVISION_PROJECTS, organization); - Integer userId = userSession.getUserId(); - - String effectiveProjectKey = ComponentKeys.createEffectiveKey(projectKey, deprecatedBranch); - boolean wouldCurrentUserHaveScanPermission = permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate( - dbSession, organization.getUuid(), userId, effectiveProjectKey, Qualifiers.PROJECT); - if (!wouldCurrentUserHaveScanPermission) { - throw insufficientPrivilegesException(); - } - - boolean newProjectPrivate = dbClient.organizationDao().getNewProjectPrivate(dbSession, organization); - - NewComponent newProject = newComponentBuilder() - .setOrganizationUuid(organization.getUuid()) - .setKey(projectKey) - .setName(defaultIfBlank(projectName, projectKey)) - .setBranch(deprecatedBranch) - .setQualifier(Qualifiers.PROJECT) - .setPrivate(newProjectPrivate) - .build(); - return componentUpdater.create(dbSession, newProject, userId); - } - - private CeTask submitReport(DbSession dbSession, InputStream reportInput, ComponentDto project, Map characteristicsMap) { - CeTaskSubmit.Builder submit = queue.prepareSubmit(); - List characteristics = characteristicsMap.entrySet().stream() - .map(e -> toDto(submit.getUuid(), e.getKey(), e.getValue())).collect(Collectors.toList()); - - // the report file must be saved before submitting the task - dbClient.ceTaskInputDao().insert(dbSession, submit.getUuid(), reportInput); - if (!characteristics.isEmpty()) { - dbClient.ceTaskCharacteristicsDao().insert(dbSession, characteristics); - } - dbSession.commit(); - - submit.setType(CeTaskTypes.REPORT); - submit.setComponentUuid(project.uuid()); - submit.setSubmitterUuid(userSession.getUuid()); - return queue.submit(submit.build()); - } - - private CeTaskCharacteristicDto toDto(String taskUuid, String key, String value) { - CeTaskCharacteristicDto dto = new CeTaskCharacteristicDto(); - dto.setTaskUuid(taskUuid); - dto.setKey(key); - dto.setValue(value); - dto.setUuid(uuidFactory.create()); - return dto; - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/package-info.java deleted file mode 100644 index 02090e8428a..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.queue; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/settings/SettingsLoader.java b/server/sonar-server/src/main/java/org/sonar/server/computation/settings/SettingsLoader.java new file mode 100644 index 00000000000..7ccf1e50b7f --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/settings/SettingsLoader.java @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.settings; + +import org.picocontainer.Startable; +import org.sonar.api.ce.ComputeEngineSide; +import org.sonar.server.computation.task.container.EagerStart; +import org.sonar.server.computation.task.container.TaskContainerImpl; +import org.sonar.server.setting.ThreadLocalSettings; + +/** + * Add this class as the first components in the {@link TaskContainerImpl} + * to trigger loading of Thread local specific {@link org.sonar.api.config.Settings} in {@link ThreadLocalSettings}. + */ +@EagerStart +@ComputeEngineSide +public class SettingsLoader implements Startable { + private final ThreadLocalSettings threadLocalSettings; + + public SettingsLoader(ThreadLocalSettings threadLocalSettings) { + this.threadLocalSettings = threadLocalSettings; + } + + @Override + public void start() { + threadLocalSettings.load(); + } + + @Override + public void stop() { + threadLocalSettings.unload(); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/settings/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/settings/package-info.java new file mode 100644 index 00000000000..dc49a51c135 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/settings/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.settings; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/TaskContainer.java b/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/TaskContainer.java index a0e388506da..ba9a14b28c0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/TaskContainer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/task/container/TaskContainer.java @@ -20,7 +20,7 @@ package org.sonar.server.computation.task.container; import org.picocontainer.PicoContainer; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.core.platform.ComponentContainer; import org.sonar.core.platform.ContainerPopulator; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolder.java index 628e722b303..5e4409b1b73 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolder.java @@ -19,7 +19,7 @@ */ package org.sonar.server.computation.taskprocessor; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTaskResult; public interface MutableTaskResultHolder extends TaskResultHolder { /** diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImpl.java index 38ecbcb93c1..6fe1e53913e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImpl.java @@ -20,7 +20,7 @@ package org.sonar.server.computation.taskprocessor; import javax.annotation.CheckForNull; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTaskResult; import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/TaskResultHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/TaskResultHolder.java index 906e4d28741..b4c3e978150 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/TaskResultHolder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/TaskResultHolder.java @@ -19,7 +19,7 @@ */ package org.sonar.server.computation.taskprocessor; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTaskResult; public interface TaskResultHolder { /** diff --git a/server/sonar-server/src/test/java/org/sonar/ce/log/CeLoggingTest.java b/server/sonar-server/src/test/java/org/sonar/ce/log/CeLoggingTest.java deleted file mode 100644 index 842160a92eb..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/ce/log/CeLoggingTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.log; - -import ch.qos.logback.core.joran.spi.JoranException; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.Mockito; -import org.slf4j.MDC; -import org.sonar.ce.queue.CeTask; -import org.sonar.process.logging.LogbackHelper; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; -import static org.sonar.ce.log.CeLogging.MDC_CE_TASK_UUID; - -public class CeLoggingTest { - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private LogbackHelper helper = new LogbackHelper(); - private CeLogging underTest = new CeLogging(); - - @After - public void resetLogback() throws JoranException { - helper.resetFromXml("/logback-test.xml"); - } - - @After - public void cleanMDC() { - MDC.clear(); - } - - @Test - public void initForTask_stores_task_uuid_in_MDC() { - String uuid = "ce_task_uuid"; - - underTest.initForTask(createCeTask(uuid)); - - assertThat(MDC.get(MDC_CE_TASK_UUID)).isEqualTo(uuid); - } - - private CeTask createCeTask(String uuid) { - CeTask ceTask = Mockito.mock(CeTask.class); - when(ceTask.getUuid()).thenReturn(uuid); - return ceTask; - } - - @Test - public void clearForTask_removes_task_uuid_from_MDC() { - MDC.put(MDC_CE_TASK_UUID, "some_value"); - - underTest.clearForTask(); - - assertThat(MDC.get(MDC_CE_TASK_UUID)).isNull(); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/ce/organization/DefaultOrganizationLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/ce/organization/DefaultOrganizationLoaderTest.java deleted file mode 100644 index b7a48ef6db0..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/ce/organization/DefaultOrganizationLoaderTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.organization; - -import org.junit.Test; -import org.sonar.server.organization.DefaultOrganizationCache; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -public class DefaultOrganizationLoaderTest { - private DefaultOrganizationCache defaultOrganizationCache = mock(DefaultOrganizationCache.class); - private DefaultOrganizationLoader underTest = new DefaultOrganizationLoader(defaultOrganizationCache); - - @Test - public void start_calls_cache_load_method() { - underTest.start(); - - verify(defaultOrganizationCache).load(); - verifyNoMoreInteractions(defaultOrganizationCache); - } - - @Test - public void stop_calls_cache_unload_method() { - underTest.stop(); - - verify(defaultOrganizationCache).unload(); - verifyNoMoreInteractions(defaultOrganizationCache); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/ce/queue/CeQueueImplTest.java b/server/sonar-server/src/test/java/org/sonar/ce/queue/CeQueueImplTest.java index bd8352216f4..bceb8f980dd 100644 --- a/server/sonar-server/src/test/java/org/sonar/ce/queue/CeQueueImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/ce/queue/CeQueueImplTest.java @@ -40,6 +40,7 @@ import org.sonar.db.ce.CeQueueDto; import org.sonar.db.ce.CeTaskTypes; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; +import org.sonar.server.computation.CeTask; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.organization.TestDefaultOrganizationProvider; diff --git a/server/sonar-server/src/test/java/org/sonar/ce/queue/CeTaskTest.java b/server/sonar-server/src/test/java/org/sonar/ce/queue/CeTaskTest.java deleted file mode 100644 index 97d20e21601..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/ce/queue/CeTaskTest.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.queue; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static org.assertj.core.api.Assertions.assertThat; - -public class CeTaskTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private CeTask.Builder underTest = new CeTask.Builder(); - - @Test - public void build_fails_with_NPE_if_organizationUuid_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("organizationUuid can't be null nor empty"); - - underTest.build(); - } - - @Test - public void build_fails_with_NPE_if_organizationUuid_is_empty() { - underTest.setOrganizationUuid(""); - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("organizationUuid can't be null nor empty"); - - underTest.build(); - } - - @Test - public void build_fails_with_NPE_if_uid_is_null() { - underTest.setOrganizationUuid("org1"); - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("uuid can't be null nor empty"); - - underTest.build(); - } - - @Test - public void build_fails_with_NPE_if_uuid_is_empty() { - underTest.setOrganizationUuid("org1").setUuid(""); - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("uuid can't be null nor empty"); - - underTest.build(); - } - - @Test - public void build_fails_with_NPE_if_type_is_null() { - underTest.setOrganizationUuid("org1").setUuid("uuid"); - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("type can't be null nor empty"); - - underTest.build(); - } - - @Test - public void build_fails_with_NPE_if_type_is_empty() { - underTest.setOrganizationUuid("org1").setUuid("uuid").setType(""); - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("type can't be null nor empty"); - - underTest.build(); - } - - @Test - public void verify_getters() { - underTest.setOrganizationUuid("org1"); - underTest.setType("TYPE_1"); - underTest.setUuid("UUID_1"); - underTest.setSubmitterUuid("LOGIN_1"); - underTest.setComponentKey("COMPONENT_KEY_1"); - underTest.setComponentUuid("COMPONENT_UUID_1"); - underTest.setComponentName("The component"); - - CeTask task = underTest.build(); - - assertThat(task.getOrganizationUuid()).isEqualTo("org1"); - assertThat(task.getUuid()).isEqualTo("UUID_1"); - assertThat(task.getType()).isEqualTo("TYPE_1"); - assertThat(task.getSubmitterUuid()).isEqualTo("LOGIN_1"); - assertThat(task.getComponentKey()).isEqualTo("COMPONENT_KEY_1"); - assertThat(task.getComponentUuid()).isEqualTo("COMPONENT_UUID_1"); - assertThat(task.getComponentName()).isEqualTo("The component"); - } - - @Test - public void empty_in_component_properties_is_considered_as_null() { - CeTask ceTask = underTest.setOrganizationUuid("org1").setUuid("uuid").setType("type") - .setComponentKey("") - .setComponentName("") - .setComponentUuid("") - .build(); - - assertThat(ceTask.getComponentKey()).isNull(); - assertThat(ceTask.getComponentName()).isNull(); - assertThat(ceTask.getComponentUuid()).isNull(); - } - - @Test - public void empty_in_submitterLogin_is_considered_as_null() { - CeTask ceTask = underTest.setOrganizationUuid("org1").setUuid("uuid").setType("type") - .setSubmitterUuid("") - .build(); - - assertThat(ceTask.getSubmitterUuid()).isNull(); - } - - @Test - public void equals_and_hashCode_on_uuid() { - underTest.setOrganizationUuid("org1").setType("TYPE_1").setUuid("UUID_1"); - CeTask task1 = underTest.build(); - CeTask task1bis = underTest.build(); - CeTask task2 = new CeTask.Builder().setOrganizationUuid("org1").setType("TYPE_1").setUuid("UUID_2").build(); - - assertThat(task1.equals(task1)).isTrue(); - assertThat(task1.equals(task1bis)).isTrue(); - assertThat(task1.equals(task2)).isFalse(); - assertThat(task1.hashCode()).isEqualTo(task1.hashCode()); - assertThat(task1.hashCode()).isEqualTo(task1bis.hashCode()); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/ce/settings/SettingsLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/ce/settings/SettingsLoaderTest.java deleted file mode 100644 index f04123a90ec..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/ce/settings/SettingsLoaderTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.ce.settings; - -import org.junit.Test; -import org.sonar.server.setting.ThreadLocalSettings; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -public class SettingsLoaderTest { - private ThreadLocalSettings threadLocalSettings = mock(ThreadLocalSettings.class); - private SettingsLoader underTest = new SettingsLoader(threadLocalSettings); - - @Test - public void start_calls_ThreadLocalSettings_load() { - underTest.start(); - - verify(threadLocalSettings).load(); - verifyNoMoreInteractions(threadLocalSettings); - } - - @Test - public void stop_calls_ThreadLocalSettings_remove() { - underTest.stop(); - - verify(threadLocalSettings).unload(); - verifyNoMoreInteractions(threadLocalSettings); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/ce/taskprocessor/ReportTaskProcessorDeclarationTest.java b/server/sonar-server/src/test/java/org/sonar/ce/taskprocessor/ReportTaskProcessorDeclarationTest.java index eb80dde6589..4c496ce8480 100644 --- a/server/sonar-server/src/test/java/org/sonar/ce/taskprocessor/ReportTaskProcessorDeclarationTest.java +++ b/server/sonar-server/src/test/java/org/sonar/ce/taskprocessor/ReportTaskProcessorDeclarationTest.java @@ -22,7 +22,7 @@ package org.sonar.ce.taskprocessor; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/queue/ReportSubmitterTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/queue/ReportSubmitterTest.java new file mode 100644 index 00000000000..5eec218d72f --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/queue/ReportSubmitterTest.java @@ -0,0 +1,329 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.ce.queue; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.io.IOUtils; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.ArgumentCaptor; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.utils.System2; +import org.sonar.ce.queue.CeQueue; +import org.sonar.ce.queue.CeQueueImpl; +import org.sonar.ce.queue.CeTaskSubmit; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.core.util.SequenceUuidFactory; +import org.sonar.core.util.UuidFactory; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.db.ce.CeTaskCharacteristicDto; +import org.sonar.db.ce.CeTaskTypes; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.ComponentTesting; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.permission.OrganizationPermission; +import org.sonar.db.user.UserDto; +import org.sonar.server.component.ComponentUpdater; +import org.sonar.server.component.NewComponent; +import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.favorite.FavoriteUpdater; +import org.sonar.server.permission.PermissionTemplateService; +import org.sonar.server.tester.UserSessionRule; + +import static java.lang.String.format; +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; +import static org.sonar.db.component.ComponentTesting.newModuleDto; +import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; +import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS; +import static org.sonar.db.permission.OrganizationPermission.SCAN; + +public class ReportSubmitterTest { + + private static final String PROJECT_KEY = "MY_PROJECT"; + private static final String PROJECT_UUID = "P1"; + private static final String PROJECT_NAME = "My Project"; + private static final String TASK_UUID = "TASK_1"; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Rule + public UserSessionRule userSession = UserSessionRule.standalone(); + @Rule + public DbTester db = DbTester.create(System2.INSTANCE); + + private String defaultOrganizationKey; + private String defaultOrganizationUuid; + private CeQueue queue = mock(CeQueueImpl.class); + private ComponentUpdater componentUpdater = mock(ComponentUpdater.class); + private PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class); + private FavoriteUpdater favoriteUpdater = mock(FavoriteUpdater.class); + private UuidFactory uuidFactory = new SequenceUuidFactory(); + + private ReportSubmitter underTest = new ReportSubmitter(queue, userSession, componentUpdater, permissionTemplateService, uuidFactory, db.getDbClient()); + + @Before + public void setUp() throws Exception { + defaultOrganizationKey = db.getDefaultOrganization().getKey(); + defaultOrganizationUuid = db.getDefaultOrganization().getUuid(); + } + + @Test + public void submit_inserts_characteristics() { + userSession + .addPermission(OrganizationPermission.SCAN, db.getDefaultOrganization().getUuid()) + .addPermission(PROVISION_PROJECTS, db.getDefaultOrganization()); + + mockSuccessfulPrepareSubmitCall(); + ComponentDto project = newPrivateProjectDto(db.getDefaultOrganization(), PROJECT_UUID).setDbKey(PROJECT_KEY); + when(componentUpdater.create(any(), any(), any())).thenReturn(project); + when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(), eq(defaultOrganizationUuid), any(), eq(PROJECT_KEY), + eq(Qualifiers.PROJECT))) + .thenReturn(true); + + Map taskCharacteristics = new HashMap<>(); + taskCharacteristics.put("incremental", "true"); + taskCharacteristics.put("pr", "mypr"); + + underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, taskCharacteristics, IOUtils.toInputStream("{binary}")); + + ArgumentCaptor submittedTask = ArgumentCaptor.forClass(CeTaskSubmit.class); + verify(queue).submit(submittedTask.capture()); + String taskUuid = submittedTask.getValue().getUuid(); + + List insertedCharacteristics = db.getDbClient().ceTaskCharacteristicsDao().selectByTaskUuids(db.getSession(), singletonList(taskUuid)); + assertThat(insertedCharacteristics) + .extracting(CeTaskCharacteristicDto::getKey, CeTaskCharacteristicDto::getValue) + .containsOnly(tuple("incremental", "true"), tuple("pr", "mypr")); + } + + @Test + public void submit_a_report_on_existing_project() { + ComponentDto project = db.components().insertPrivateProject(db.getDefaultOrganization()); + UserDto user = db.users().insertUser(); + userSession.logIn(user).addProjectPermission(SCAN_EXECUTION, project); + + mockSuccessfulPrepareSubmitCall(); + + underTest.submit(defaultOrganizationKey, project.getDbKey(), null, project.name(), IOUtils.toInputStream("{binary}")); + + verifyReportIsPersisted(TASK_UUID); + verifyZeroInteractions(permissionTemplateService); + verifyZeroInteractions(favoriteUpdater); + verify(queue).submit(argThat(submit -> + submit.getType().equals(CeTaskTypes.REPORT) + && submit.getComponentUuid().equals(project.uuid()) + && submit.getSubmitterUuid().equals(user.getUuid()) + && submit.getUuid().equals(TASK_UUID))); + } + + @Test + public void provision_project_if_does_not_exist() { + OrganizationDto organization = db.organizations().insert(); + userSession + .addPermission(OrganizationPermission.SCAN, organization.getUuid()) + .addPermission(PROVISION_PROJECTS, organization); + + mockSuccessfulPrepareSubmitCall(); + ComponentDto createdProject = newPrivateProjectDto(organization, PROJECT_UUID).setDbKey(PROJECT_KEY); + when(componentUpdater.create(any(), any(), isNull())).thenReturn(createdProject); + when( + permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(), eq(organization.getUuid()), any(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) + .thenReturn(true); + when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(), eq(organization.getUuid()), any())).thenReturn(true); + + underTest.submit(organization.getKey(), PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); + + verifyReportIsPersisted(TASK_UUID); + verify(queue).submit(argThat(submit -> + submit.getType().equals(CeTaskTypes.REPORT) && submit.getComponentUuid().equals(PROJECT_UUID) && submit.getUuid().equals(TASK_UUID))); + } + + @Test + public void no_favorite_when_no_project_creator_permission_on_permission_template() { + userSession + .addPermission(OrganizationPermission.SCAN, db.getDefaultOrganization().getUuid()) + .addPermission(PROVISION_PROJECTS, db.getDefaultOrganization()); + + mockSuccessfulPrepareSubmitCall(); + ComponentDto createdProject = newPrivateProjectDto(db.getDefaultOrganization(), PROJECT_UUID).setDbKey(PROJECT_KEY); + when(componentUpdater.create(any(), any(), isNull())).thenReturn(createdProject); + when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(), eq(defaultOrganizationUuid), any(), + eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) + .thenReturn(true); + when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(), eq(defaultOrganizationUuid), any())).thenReturn(false); + + underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); + + verifyZeroInteractions(favoriteUpdater); + } + + @Test + public void submit_a_report_on_new_project_with_scan_permission_on_organization() { + userSession + .addPermission(OrganizationPermission.SCAN, db.getDefaultOrganization().getUuid()) + .addPermission(PROVISION_PROJECTS, db.getDefaultOrganization()); + + mockSuccessfulPrepareSubmitCall(); + ComponentDto project = newPrivateProjectDto(db.getDefaultOrganization(), PROJECT_UUID).setDbKey(PROJECT_KEY); + when(componentUpdater.create(any(), any(), any())).thenReturn(project); + when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(), eq(defaultOrganizationUuid), any(), + eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) + .thenReturn(true); + + underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); + + verify(queue).submit(any(CeTaskSubmit.class)); + } + + @Test + public void user_with_scan_permission_on_organization_is_allowed_to_submit_a_report_on_existing_project() { + OrganizationDto org = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(org); + userSession.addPermission(SCAN, org); + + mockSuccessfulPrepareSubmitCall(); + + underTest.submit(org.getKey(), project.getDbKey(), null, project.name(), IOUtils.toInputStream("{binary}")); + + verify(queue).submit(any(CeTaskSubmit.class)); + } + + @Test + public void submit_a_report_on_existing_project_with_project_scan_permission() { + ComponentDto project = db.components().insertPrivateProject(db.getDefaultOrganization()); + userSession.addProjectPermission(SCAN_EXECUTION, project); + + mockSuccessfulPrepareSubmitCall(); + + underTest.submit(defaultOrganizationKey, project.getDbKey(), null, project.name(), IOUtils.toInputStream("{binary}")); + + verify(queue).submit(any(CeTaskSubmit.class)); + } + + /** + * SONAR-8757 + */ + @Test + public void project_branch_must_not_benefit_from_the_scan_permission_on_main_project() { + ComponentDto mainProject = db.components().insertPrivateProject(); + userSession.addProjectPermission(GlobalPermissions.SCAN_EXECUTION, mainProject); + + // user does not have the "scan" permission on the branch, so it can't scan it + String branchName = "branchFoo"; + ComponentDto branchProject = db.components().insertPrivateProject(p -> p.setDbKey(mainProject.getDbKey() + ":" + branchName)); + + expectedException.expect(ForbiddenException.class); + underTest.submit(defaultOrganizationKey, mainProject.getDbKey(), branchName, PROJECT_NAME, IOUtils.toInputStream("{binary}")); + } + + @Test + public void fail_with_NotFoundException_if_organization_with_specified_key_does_not_exist() { + expectedException.expect(NotFoundException.class); + expectedException.expectMessage("Organization with key 'fop' does not exist"); + + underTest.submit("fop", PROJECT_KEY, null, null, null /* method will fail before parameter is used */); + } + + @Test + public void fail_with_organizationKey_does_not_match_organization_of_specified_component() { + userSession.logIn().setRoot(); + OrganizationDto organization = db.organizations().insert(); + ComponentDto project = db.components().insertPrivateProject(organization); + mockSuccessfulPrepareSubmitCall(); + + underTest.submit(organization.getKey(), project.getDbKey(), null, project.name(), IOUtils.toInputStream("{binary}")); + } + + @Test + public void fail_if_component_is_not_a_project() { + ComponentDto component = db.components().insertPublicPortfolio(db.getDefaultOrganization()); + userSession.logIn().addProjectPermission(SCAN_EXECUTION, component); + mockSuccessfulPrepareSubmitCall(); + + expectedException.expect(BadRequestException.class); + expectedException.expectMessage(format("Component '%s' is not a project", component.getKey())); + + underTest.submit(defaultOrganizationKey, component.getDbKey(), null, component.name(), IOUtils.toInputStream("{binary}")); + } + + @Test + public void fail_if_project_key_already_exists_as_module() { + ComponentDto project = db.components().insertPrivateProject(db.getDefaultOrganization()); + ComponentDto module = db.components().insertComponent(newModuleDto(project)); + userSession.logIn().addProjectPermission(SCAN_EXECUTION, project); + mockSuccessfulPrepareSubmitCall(); + + try { + underTest.submit(defaultOrganizationKey, module.getDbKey(), null, module.name(), IOUtils.toInputStream("{binary}")); + fail(); + } catch (BadRequestException e) { + assertThat(e.errors()).contains( + format("The project '%s' is already defined in SonarQube but as a module of project '%s'. " + + "If you really want to stop directly analysing project '%s', please first delete it from SonarQube and then relaunch the analysis of project '%s'.", + module.getKey(), project.getKey(), project.getKey(), module.getKey())); + } + } + + @Test + public void fail_with_forbidden_exception_when_no_scan_permission() { + expectedException.expect(ForbiddenException.class); + + underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); + } + + @Test + public void fail_with_forbidden_exception_on_new_project_when_only_project_scan_permission() { + userSession.addProjectPermission(SCAN_EXECUTION, ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), PROJECT_UUID)); + + mockSuccessfulPrepareSubmitCall(); + when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setDbKey(PROJECT_KEY)); + + expectedException.expect(ForbiddenException.class); + underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); + } + + private void verifyReportIsPersisted(String taskUuid) { + assertThat(db.selectFirst("select task_uuid from ce_task_input where task_uuid='" + taskUuid + "'")).isNotNull(); + } + + private void mockSuccessfulPrepareSubmitCall() { + when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder(TASK_UUID)); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/CancelActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/CancelActionTest.java index 541edc1d049..b3b5561a9a3 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/CancelActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/CancelActionTest.java @@ -26,7 +26,7 @@ import org.junit.rules.ExpectedException; import org.sonar.api.web.UserRole; import org.sonar.ce.queue.CeQueue; import org.sonar.ce.queue.CeQueueImpl; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.ce.queue.CeTaskSubmit; import org.sonar.core.util.UuidFactoryFast; import org.sonar.db.DbTester; diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/CeWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/CeWsTest.java index 4fc3633bc2b..d5cead2759d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/CeWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/CeWsTest.java @@ -22,7 +22,7 @@ package org.sonar.server.ce.ws; import org.junit.Test; import org.mockito.Mockito; import org.sonar.api.server.ws.WebService; -import org.sonar.server.computation.queue.ReportSubmitter; +import org.sonar.server.ce.queue.ReportSubmitter; import org.sonar.server.organization.DefaultOrganizationProvider; import static org.assertj.core.api.Assertions.assertThat; diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/SubmitActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/SubmitActionTest.java index 32540048c7d..6073f05a9cb 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/SubmitActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/SubmitActionTest.java @@ -29,9 +29,9 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.MockitoAnnotations; -import org.sonar.ce.queue.CeTask; +import org.sonar.server.computation.CeTask; import org.sonar.db.ce.CeTaskTypes; -import org.sonar.server.computation.queue.ReportSubmitter; +import org.sonar.server.ce.queue.ReportSubmitter; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.organization.TestDefaultOrganizationProvider; import org.sonar.server.ws.TestResponse; diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskTypesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskTypesActionTest.java index c7f683d6cd9..627e25d28b0 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskTypesActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskTypesActionTest.java @@ -22,8 +22,8 @@ package org.sonar.server.ce.ws; import com.google.common.collect.ImmutableSet; import java.util.Set; import org.junit.Test; -import org.sonar.ce.queue.CeTask; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTask; +import org.sonar.server.computation.CeTaskResult; import org.sonar.ce.taskprocessor.CeTaskProcessor; import org.sonar.server.ws.WsActionTester; diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/CeTaskTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/CeTaskTest.java new file mode 100644 index 00000000000..b42261f5eb7 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/CeTaskTest.java @@ -0,0 +1,148 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CeTaskTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private CeTask.Builder underTest = new CeTask.Builder(); + + @Test + public void build_fails_with_NPE_if_organizationUuid_is_null() { + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("organizationUuid can't be null nor empty"); + + underTest.build(); + } + + @Test + public void build_fails_with_NPE_if_organizationUuid_is_empty() { + underTest.setOrganizationUuid(""); + + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("organizationUuid can't be null nor empty"); + + underTest.build(); + } + + @Test + public void build_fails_with_NPE_if_uid_is_null() { + underTest.setOrganizationUuid("org1"); + + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("uuid can't be null nor empty"); + + underTest.build(); + } + + @Test + public void build_fails_with_NPE_if_uuid_is_empty() { + underTest.setOrganizationUuid("org1").setUuid(""); + + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("uuid can't be null nor empty"); + + underTest.build(); + } + + @Test + public void build_fails_with_NPE_if_type_is_null() { + underTest.setOrganizationUuid("org1").setUuid("uuid"); + + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("type can't be null nor empty"); + + underTest.build(); + } + + @Test + public void build_fails_with_NPE_if_type_is_empty() { + underTest.setOrganizationUuid("org1").setUuid("uuid").setType(""); + + expectedException.expect(NullPointerException.class); + expectedException.expectMessage("type can't be null nor empty"); + + underTest.build(); + } + + @Test + public void verify_getters() { + underTest.setOrganizationUuid("org1"); + underTest.setType("TYPE_1"); + underTest.setUuid("UUID_1"); + underTest.setSubmitterUuid("LOGIN_1"); + underTest.setComponentKey("COMPONENT_KEY_1"); + underTest.setComponentUuid("COMPONENT_UUID_1"); + underTest.setComponentName("The component"); + + CeTask task = underTest.build(); + + assertThat(task.getOrganizationUuid()).isEqualTo("org1"); + assertThat(task.getUuid()).isEqualTo("UUID_1"); + assertThat(task.getType()).isEqualTo("TYPE_1"); + assertThat(task.getSubmitterUuid()).isEqualTo("LOGIN_1"); + assertThat(task.getComponentKey()).isEqualTo("COMPONENT_KEY_1"); + assertThat(task.getComponentUuid()).isEqualTo("COMPONENT_UUID_1"); + assertThat(task.getComponentName()).isEqualTo("The component"); + } + + @Test + public void empty_in_component_properties_is_considered_as_null() { + CeTask ceTask = underTest.setOrganizationUuid("org1").setUuid("uuid").setType("type") + .setComponentKey("") + .setComponentName("") + .setComponentUuid("") + .build(); + + assertThat(ceTask.getComponentKey()).isNull(); + assertThat(ceTask.getComponentName()).isNull(); + assertThat(ceTask.getComponentUuid()).isNull(); + } + + @Test + public void empty_in_submitterLogin_is_considered_as_null() { + CeTask ceTask = underTest.setOrganizationUuid("org1").setUuid("uuid").setType("type") + .setSubmitterUuid("") + .build(); + + assertThat(ceTask.getSubmitterUuid()).isNull(); + } + + @Test + public void equals_and_hashCode_on_uuid() { + underTest.setOrganizationUuid("org1").setType("TYPE_1").setUuid("UUID_1"); + CeTask task1 = underTest.build(); + CeTask task1bis = underTest.build(); + CeTask task2 = new CeTask.Builder().setOrganizationUuid("org1").setType("TYPE_1").setUuid("UUID_2").build(); + + assertThat(task1.equals(task1)).isTrue(); + assertThat(task1.equals(task1bis)).isTrue(); + assertThat(task1.equals(task2)).isFalse(); + assertThat(task1.hashCode()).isEqualTo(task1.hashCode()); + assertThat(task1.hashCode()).isEqualTo(task1bis.hashCode()); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/IndexPurgeListenerTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/IndexPurgeListenerTest.java deleted file mode 100644 index a1d8afc8ae6..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/IndexPurgeListenerTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.dbcleaner; - -import java.util.Arrays; -import java.util.List; -import org.junit.Test; -import org.sonar.server.component.index.ComponentIndexer; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.test.index.TestIndexer; - -import static java.util.Arrays.asList; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -public class IndexPurgeListenerTest { - - TestIndexer testIndexer = mock(TestIndexer.class); - IssueIndexer issueIndexer = mock(IssueIndexer.class); - ComponentIndexer componentIndexer = mock(ComponentIndexer.class); - - IndexPurgeListener underTest = new IndexPurgeListener(testIndexer, issueIndexer, componentIndexer); - - @Test - public void test_onComponentDisabling() { - String uuid = "123456"; - String projectUuid = "P789"; - List uuids = Arrays.asList(uuid); - underTest.onComponentsDisabling(projectUuid, uuids); - - verify(testIndexer).deleteByFile(uuid); - verify(componentIndexer).delete(projectUuid, uuids); - } - - @Test - public void test_onIssuesRemoval() { - underTest.onIssuesRemoval("P1", asList("ISSUE1", "ISSUE2")); - - verify(issueIndexer).deleteByKeys("P1", asList("ISSUE1", "ISSUE2")); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/ProjectCleanerTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/ProjectCleanerTest.java deleted file mode 100644 index 12ae7f4eefd..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/dbcleaner/ProjectCleanerTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.dbcleaner; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.PropertyDefinitions; -import org.sonar.api.config.internal.MapSettings; -import org.sonar.core.config.PurgeConstants; -import org.sonar.core.config.PurgeProperties; -import org.sonar.db.DbSession; -import org.sonar.db.purge.IdUuidPair; -import org.sonar.db.purge.PurgeDao; -import org.sonar.db.purge.PurgeListener; -import org.sonar.db.purge.PurgeProfiler; -import org.sonar.db.purge.period.DefaultPeriodCleaner; - -import static java.util.Collections.emptyList; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -public class ProjectCleanerTest { - - private ProjectCleaner underTest; - private PurgeDao dao = mock(PurgeDao.class); - private PurgeProfiler profiler = mock(PurgeProfiler.class); - private DefaultPeriodCleaner periodCleaner = mock(DefaultPeriodCleaner.class); - private PurgeListener purgeListener = mock(PurgeListener.class); - private MapSettings settings = new MapSettings(new PropertyDefinitions(PurgeProperties.all())); - - @Before - public void before() { - this.underTest = new ProjectCleaner(dao, periodCleaner, profiler, purgeListener); - } - - @Test - public void no_profiling_when_property_is_false() { - settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, false); - - underTest.purge(mock(DbSession.class), mock(IdUuidPair.class), settings.asConfig(), emptyList()); - - verify(profiler, never()).dump(anyLong(), any()); - } - - @Test - public void profiling_when_property_is_true() { - settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, true); - - underTest.purge(mock(DbSession.class), mock(IdUuidPair.class), settings.asConfig(), emptyList()); - - verify(profiler).dump(anyLong(), any()); - } - - @Test - public void call_period_cleaner_index_client_and_purge_dao() { - settings.setProperty(PurgeConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES, 5); - - underTest.purge(mock(DbSession.class), mock(IdUuidPair.class), settings.asConfig(), emptyList()); - - verify(periodCleaner).clean(any(), any(), any()); - verify(dao).purge(any(), any(), any(), any()); - } -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/log/CeTaskLoggingTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/log/CeTaskLoggingTest.java new file mode 100644 index 00000000000..5193eb1efd8 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/log/CeTaskLoggingTest.java @@ -0,0 +1,78 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.log; + +import ch.qos.logback.core.joran.spi.JoranException; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; +import org.slf4j.MDC; +import org.sonar.process.logging.LogbackHelper; +import org.sonar.server.computation.CeTask; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; +import static org.sonar.server.computation.log.CeTaskLogging.MDC_CE_TASK_UUID; + +public class CeTaskLoggingTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private LogbackHelper helper = new LogbackHelper(); + private CeTaskLogging underTest = new CeTaskLogging(); + + @After + public void resetLogback() throws JoranException { + helper.resetFromXml("/logback-test.xml"); + } + + @After + public void cleanMDC() { + MDC.clear(); + } + + @Test + public void initForTask_stores_task_uuid_in_MDC() { + String uuid = "ce_task_uuid"; + + underTest.initForTask(createCeTask(uuid)); + + assertThat(MDC.get(MDC_CE_TASK_UUID)).isEqualTo(uuid); + } + + private CeTask createCeTask(String uuid) { + CeTask ceTask = Mockito.mock(CeTask.class); + when(ceTask.getUuid()).thenReturn(uuid); + return ceTask; + } + + @Test + public void clearForTask_removes_task_uuid_from_MDC() { + MDC.put(MDC_CE_TASK_UUID, "some_value"); + + underTest.clearForTask(); + + assertThat(MDC.get(MDC_CE_TASK_UUID)).isNull(); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/organization/DefaultOrganizationLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/organization/DefaultOrganizationLoaderTest.java new file mode 100644 index 00000000000..1cdd4fa8b57 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/organization/DefaultOrganizationLoaderTest.java @@ -0,0 +1,48 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.organization; + +import org.junit.Test; +import org.sonar.server.organization.DefaultOrganizationCache; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +public class DefaultOrganizationLoaderTest { + private DefaultOrganizationCache defaultOrganizationCache = mock(DefaultOrganizationCache.class); + private DefaultOrganizationLoader underTest = new DefaultOrganizationLoader(defaultOrganizationCache); + + @Test + public void start_calls_cache_load_method() { + underTest.start(); + + verify(defaultOrganizationCache).load(); + verifyNoMoreInteractions(defaultOrganizationCache); + } + + @Test + public void stop_calls_cache_unload_method() { + underTest.stop(); + + verify(defaultOrganizationCache).unload(); + verifyNoMoreInteractions(defaultOrganizationCache); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java deleted file mode 100644 index 94693054919..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/ReportSubmitterTest.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program 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. - * - * This program 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.computation.queue; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.apache.commons.io.IOUtils; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.ArgumentCaptor; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.utils.System2; -import org.sonar.ce.queue.CeQueue; -import org.sonar.ce.queue.CeQueueImpl; -import org.sonar.ce.queue.CeTaskSubmit; -import org.sonar.core.permission.GlobalPermissions; -import org.sonar.core.util.SequenceUuidFactory; -import org.sonar.core.util.UuidFactory; -import org.sonar.db.DbSession; -import org.sonar.db.DbTester; -import org.sonar.db.ce.CeTaskCharacteristicDto; -import org.sonar.db.ce.CeTaskTypes; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ComponentTesting; -import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.permission.OrganizationPermission; -import org.sonar.db.user.UserDto; -import org.sonar.server.component.ComponentUpdater; -import org.sonar.server.component.NewComponent; -import org.sonar.server.exceptions.BadRequestException; -import org.sonar.server.exceptions.ForbiddenException; -import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.favorite.FavoriteUpdater; -import org.sonar.server.permission.PermissionTemplateService; -import org.sonar.server.tester.UserSessionRule; - -import static java.lang.String.format; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; -import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; -import static org.sonar.db.component.ComponentTesting.newModuleDto; -import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; -import static org.sonar.db.permission.OrganizationPermission.PROVISION_PROJECTS; -import static org.sonar.db.permission.OrganizationPermission.SCAN; - -public class ReportSubmitterTest { - - private static final String PROJECT_KEY = "MY_PROJECT"; - private static final String PROJECT_UUID = "P1"; - private static final String PROJECT_NAME = "My Project"; - private static final String TASK_UUID = "TASK_1"; - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Rule - public UserSessionRule userSession = UserSessionRule.standalone(); - @Rule - public DbTester db = DbTester.create(System2.INSTANCE); - - private String defaultOrganizationKey; - private String defaultOrganizationUuid; - private CeQueue queue = mock(CeQueueImpl.class); - private ComponentUpdater componentUpdater = mock(ComponentUpdater.class); - private PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class); - private FavoriteUpdater favoriteUpdater = mock(FavoriteUpdater.class); - private UuidFactory uuidFactory = new SequenceUuidFactory(); - - private ReportSubmitter underTest = new ReportSubmitter(queue, userSession, componentUpdater, permissionTemplateService, uuidFactory, db.getDbClient()); - - @Before - public void setUp() throws Exception { - defaultOrganizationKey = db.getDefaultOrganization().getKey(); - defaultOrganizationUuid = db.getDefaultOrganization().getUuid(); - } - - @Test - public void submit_inserts_characteristics() { - userSession - .addPermission(OrganizationPermission.SCAN, db.getDefaultOrganization().getUuid()) - .addPermission(PROVISION_PROJECTS, db.getDefaultOrganization()); - - mockSuccessfulPrepareSubmitCall(); - ComponentDto project = newPrivateProjectDto(db.getDefaultOrganization(), PROJECT_UUID).setDbKey(PROJECT_KEY); - when(componentUpdater.create(any(), any(), any())).thenReturn(project); - when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(), eq(defaultOrganizationUuid), any(), eq(PROJECT_KEY), - eq(Qualifiers.PROJECT))) - .thenReturn(true); - - Map taskCharacteristics = new HashMap<>(); - taskCharacteristics.put("incremental", "true"); - taskCharacteristics.put("pr", "mypr"); - - underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, taskCharacteristics, IOUtils.toInputStream("{binary}")); - - ArgumentCaptor submittedTask = ArgumentCaptor.forClass(CeTaskSubmit.class); - verify(queue).submit(submittedTask.capture()); - String taskUuid = submittedTask.getValue().getUuid(); - - List insertedCharacteristics = db.getDbClient().ceTaskCharacteristicsDao().selectByTaskUuids(db.getSession(), singletonList(taskUuid)); - assertThat(insertedCharacteristics) - .extracting(CeTaskCharacteristicDto::getKey, CeTaskCharacteristicDto::getValue) - .containsOnly(tuple("incremental", "true"), tuple("pr", "mypr")); - } - - @Test - public void submit_a_report_on_existing_project() { - ComponentDto project = db.components().insertPrivateProject(db.getDefaultOrganization()); - UserDto user = db.users().insertUser(); - userSession.logIn(user).addProjectPermission(SCAN_EXECUTION, project); - - mockSuccessfulPrepareSubmitCall(); - - underTest.submit(defaultOrganizationKey, project.getDbKey(), null, project.name(), IOUtils.toInputStream("{binary}")); - - verifyReportIsPersisted(TASK_UUID); - verifyZeroInteractions(permissionTemplateService); - verifyZeroInteractions(favoriteUpdater); - verify(queue).submit(argThat(submit -> - submit.getType().equals(CeTaskTypes.REPORT) - && submit.getComponentUuid().equals(project.uuid()) - && submit.getSubmitterUuid().equals(user.getUuid()) - && submit.getUuid().equals(TASK_UUID))); - } - - @Test - public void provision_project_if_does_not_exist() { - OrganizationDto organization = db.organizations().insert(); - userSession - .addPermission(OrganizationPermission.SCAN, organization.getUuid()) - .addPermission(PROVISION_PROJECTS, organization); - - mockSuccessfulPrepareSubmitCall(); - ComponentDto createdProject = newPrivateProjectDto(organization, PROJECT_UUID).setDbKey(PROJECT_KEY); - when(componentUpdater.create(any(), any(), isNull())).thenReturn(createdProject); - when( - permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(), eq(organization.getUuid()), any(), eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) - .thenReturn(true); - when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(), eq(organization.getUuid()), any())).thenReturn(true); - - underTest.submit(organization.getKey(), PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); - - verifyReportIsPersisted(TASK_UUID); - verify(queue).submit(argThat(submit -> - submit.getType().equals(CeTaskTypes.REPORT) && submit.getComponentUuid().equals(PROJECT_UUID) && submit.getUuid().equals(TASK_UUID))); - } - - @Test - public void no_favorite_when_no_project_creator_permission_on_permission_template() { - userSession - .addPermission(OrganizationPermission.SCAN, db.getDefaultOrganization().getUuid()) - .addPermission(PROVISION_PROJECTS, db.getDefaultOrganization()); - - mockSuccessfulPrepareSubmitCall(); - ComponentDto createdProject = newPrivateProjectDto(db.getDefaultOrganization(), PROJECT_UUID).setDbKey(PROJECT_KEY); - when(componentUpdater.create(any(), any(), isNull())).thenReturn(createdProject); - when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(), eq(defaultOrganizationUuid), any(), - eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) - .thenReturn(true); - when(permissionTemplateService.hasDefaultTemplateWithPermissionOnProjectCreator(any(), eq(defaultOrganizationUuid), any())).thenReturn(false); - - underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); - - verifyZeroInteractions(favoriteUpdater); - } - - @Test - public void submit_a_report_on_new_project_with_scan_permission_on_organization() { - userSession - .addPermission(OrganizationPermission.SCAN, db.getDefaultOrganization().getUuid()) - .addPermission(PROVISION_PROJECTS, db.getDefaultOrganization()); - - mockSuccessfulPrepareSubmitCall(); - ComponentDto project = newPrivateProjectDto(db.getDefaultOrganization(), PROJECT_UUID).setDbKey(PROJECT_KEY); - when(componentUpdater.create(any(), any(), any())).thenReturn(project); - when(permissionTemplateService.wouldUserHaveScanPermissionWithDefaultTemplate(any(), eq(defaultOrganizationUuid), any(), - eq(PROJECT_KEY), eq(Qualifiers.PROJECT))) - .thenReturn(true); - - underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); - - verify(queue).submit(any(CeTaskSubmit.class)); - } - - @Test - public void user_with_scan_permission_on_organization_is_allowed_to_submit_a_report_on_existing_project() { - OrganizationDto org = db.organizations().insert(); - ComponentDto project = db.components().insertPrivateProject(org); - userSession.addPermission(SCAN, org); - - mockSuccessfulPrepareSubmitCall(); - - underTest.submit(org.getKey(), project.getDbKey(), null, project.name(), IOUtils.toInputStream("{binary}")); - - verify(queue).submit(any(CeTaskSubmit.class)); - } - - @Test - public void submit_a_report_on_existing_project_with_project_scan_permission() { - ComponentDto project = db.components().insertPrivateProject(db.getDefaultOrganization()); - userSession.addProjectPermission(SCAN_EXECUTION, project); - - mockSuccessfulPrepareSubmitCall(); - - underTest.submit(defaultOrganizationKey, project.getDbKey(), null, project.name(), IOUtils.toInputStream("{binary}")); - - verify(queue).submit(any(CeTaskSubmit.class)); - } - - /** - * SONAR-8757 - */ - @Test - public void project_branch_must_not_benefit_from_the_scan_permission_on_main_project() { - ComponentDto mainProject = db.components().insertPrivateProject(); - userSession.addProjectPermission(GlobalPermissions.SCAN_EXECUTION, mainProject); - - // user does not have the "scan" permission on the branch, so it can't scan it - String branchName = "branchFoo"; - ComponentDto branchProject = db.components().insertPrivateProject(p -> p.setDbKey(mainProject.getDbKey() + ":" + branchName)); - - expectedException.expect(ForbiddenException.class); - underTest.submit(defaultOrganizationKey, mainProject.getDbKey(), branchName, PROJECT_NAME, IOUtils.toInputStream("{binary}")); - } - - @Test - public void fail_with_NotFoundException_if_organization_with_specified_key_does_not_exist() { - expectedException.expect(NotFoundException.class); - expectedException.expectMessage("Organization with key 'fop' does not exist"); - - underTest.submit("fop", PROJECT_KEY, null, null, null /* method will fail before parameter is used */); - } - - @Test - public void fail_with_organizationKey_does_not_match_organization_of_specified_component() { - userSession.logIn().setRoot(); - OrganizationDto organization = db.organizations().insert(); - ComponentDto project = db.components().insertPrivateProject(organization); - mockSuccessfulPrepareSubmitCall(); - - underTest.submit(organization.getKey(), project.getDbKey(), null, project.name(), IOUtils.toInputStream("{binary}")); - } - - @Test - public void fail_if_component_is_not_a_project() { - ComponentDto component = db.components().insertPublicPortfolio(db.getDefaultOrganization()); - userSession.logIn().addProjectPermission(SCAN_EXECUTION, component); - mockSuccessfulPrepareSubmitCall(); - - expectedException.expect(BadRequestException.class); - expectedException.expectMessage(format("Component '%s' is not a project", component.getKey())); - - underTest.submit(defaultOrganizationKey, component.getDbKey(), null, component.name(), IOUtils.toInputStream("{binary}")); - } - - @Test - public void fail_if_project_key_already_exists_as_module() { - ComponentDto project = db.components().insertPrivateProject(db.getDefaultOrganization()); - ComponentDto module = db.components().insertComponent(newModuleDto(project)); - userSession.logIn().addProjectPermission(SCAN_EXECUTION, project); - mockSuccessfulPrepareSubmitCall(); - - try { - underTest.submit(defaultOrganizationKey, module.getDbKey(), null, module.name(), IOUtils.toInputStream("{binary}")); - fail(); - } catch (BadRequestException e) { - assertThat(e.errors()).contains( - format("The project '%s' is already defined in SonarQube but as a module of project '%s'. " + - "If you really want to stop directly analysing project '%s', please first delete it from SonarQube and then relaunch the analysis of project '%s'.", - module.getKey(), project.getKey(), project.getKey(), module.getKey())); - } - } - - @Test - public void fail_with_forbidden_exception_when_no_scan_permission() { - expectedException.expect(ForbiddenException.class); - - underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); - } - - @Test - public void fail_with_forbidden_exception_on_new_project_when_only_project_scan_permission() { - userSession.addProjectPermission(SCAN_EXECUTION, ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization(), PROJECT_UUID)); - - mockSuccessfulPrepareSubmitCall(); - when(componentUpdater.create(any(DbSession.class), any(NewComponent.class), eq(null))).thenReturn(new ComponentDto().setUuid(PROJECT_UUID).setDbKey(PROJECT_KEY)); - - expectedException.expect(ForbiddenException.class); - underTest.submit(defaultOrganizationKey, PROJECT_KEY, null, PROJECT_NAME, IOUtils.toInputStream("{binary}")); - } - - private void verifyReportIsPersisted(String taskUuid) { - assertThat(db.selectFirst("select task_uuid from ce_task_input where task_uuid='" + taskUuid + "'")).isNotNull(); - } - - private void mockSuccessfulPrepareSubmitCall() { - when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit.Builder(TASK_UUID)); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/settings/SettingsLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/settings/SettingsLoaderTest.java new file mode 100644 index 00000000000..f0c5cf58ef9 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/settings/SettingsLoaderTest.java @@ -0,0 +1,48 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.computation.settings; + +import org.junit.Test; +import org.sonar.server.setting.ThreadLocalSettings; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +public class SettingsLoaderTest { + private ThreadLocalSettings threadLocalSettings = mock(ThreadLocalSettings.class); + private SettingsLoader underTest = new SettingsLoader(threadLocalSettings); + + @Test + public void start_calls_ThreadLocalSettings_load() { + underTest.start(); + + verify(threadLocalSettings).load(); + verifyNoMoreInteractions(threadLocalSettings); + } + + @Test + public void stop_calls_ThreadLocalSettings_remove() { + underTest.stop(); + + verify(threadLocalSettings).unload(); + verifyNoMoreInteractions(threadLocalSettings); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImplTest.java index 277ae458f7a..f81de440ad6 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/taskprocessor/MutableTaskResultHolderImplTest.java @@ -23,7 +23,7 @@ import org.assertj.core.api.Assertions; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.ce.queue.CeTaskResult; +import org.sonar.server.computation.CeTaskResult; import static org.mockito.Mockito.mock;