summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/batch/BatchWsModule.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java11
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/CeQueue.java230
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/CeQueueInitializer.java110
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/CeQueueListener.java (renamed from server/sonar-server/src/main/java/org/sonar/server/computation/activity/package-info.java)10
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/CeTask.java101
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/CeTaskSubmit.java (renamed from server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueCleanerTest.java)50
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/CeWorker.java (renamed from server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineTask.java)4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/CeWorkerImpl.java66
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/CleanReportQueueListener.java36
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputationStepExecutor.java79
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingExecutorService.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingModule.java5
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingQueue.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingQueueImpl.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportFiles.java95
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingScheduler.java26
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingSchedulerExecutorService.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingTask.java74
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessor.java90
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java195
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueueCleaner.java59
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportSubmitter.java71
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ReportTaskProcessor.java44
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/activity/ActivityManager.java72
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportDirectoryHolder.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportDirectoryHolderImpl.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainer.java5
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/container/ContainerFactory.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/container/ContainerFactoryImpl.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java166
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/ComputeEngineQueueMonitor.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolder.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolder.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportExtractionStep.java30
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeSubmitWsAction.java93
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeTaskWsAction.java93
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeWs.java (renamed from server/sonar-server/src/main/java/org/sonar/server/computation/ws/ComputationWs.java)21
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeWsAction.java (renamed from server/sonar-server/src/main/java/org/sonar/server/computation/ws/ComputationWsAction.java)5
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeWsTaskFormatter.java89
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryAction.java90
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/IsQueueEmptyWs.java29
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueAction.java80
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportAction.java100
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java27
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java3
-rw-r--r--server/sonar-server/src/main/resources/org/sonar/server/computation/ws/CeSubmitWsAction/example.json4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsModuleTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java5
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/CeQueueInitializerTest.java139
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/CeQueueTest.java219
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/CeWorkerImplTest.java72
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/CleanReportQueueListenerTest.java49
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ComputeEngineProcessingQueueImplTest.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessingSchedulerTest.java48
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessingTaskTest.java111
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessorTest.java151
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java210
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ReportSubmitterTest.java69
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/activity/ActivityManagerTest.java84
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulatorTest.java8
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/ComputeEngineQueueMonitorTest.java4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportExtractionStepTest.java204
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ws/CeSubmitWsActionTest.java105
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ws/CeTaskWsActionTest.java129
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ws/CeWsTest.java (renamed from server/sonar-server/src/test/java/org/sonar/server/computation/ws/ComputationWsTest.java)27
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryActionMediumTest.java91
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ws/IsQueueEmptyWsTest.java98
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueActionTest.java71
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportActionTest.java105
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/ws/TestRequest.java7
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryActionMediumTest/list_history_reports.json16
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/computation/ws/QueueActionTest/list_queue_reports.json13
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/db/migrate/414_add_scan_and_dry_run_permissions.rb4
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/db/migrate/931_create_ce_activity.rb45
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/db/migrate/932_create_ce_queue.rb40
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/db/migrate/933_drop_table_analysis_reports.rb30
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/db/migrate/934_remove_analysis_reports_from_activities.rb30
82 files changed, 2333 insertions, 2187 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/BatchWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/batch/BatchWsModule.java
index 8357272f318..2d0f594eefe 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/batch/BatchWsModule.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/batch/BatchWsModule.java
@@ -20,7 +20,6 @@
package org.sonar.server.batch;
import org.sonar.core.platform.Module;
-import org.sonar.server.computation.ws.SubmitReportAction;
public class BatchWsModule extends Module {
@Override
@@ -30,7 +29,6 @@ public class BatchWsModule extends Module {
GlobalAction.class,
ProjectAction.class,
ProjectRepositoryLoader.class,
- SubmitReportAction.class,
IssuesAction.class,
UsersAction.class,
BatchWs.class);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java
index 1530536274a..8c9b2c7c109 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java
@@ -144,7 +144,7 @@ public class ComponentService {
}
}
- public String create(NewComponent newComponent) {
+ public ComponentDto create(NewComponent newComponent) {
userSession.checkGlobalPermission(GlobalPermissions.PROVISIONING);
DbSession session = dbClient.openSession(false);
@@ -175,9 +175,9 @@ public class ComponentService {
dbClient.componentIndexDao().indexResource(session, component.getId());
session.commit();
- return component.key();
+ return component;
} finally {
- session.close();
+ dbClient.closeSession(session);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java b/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java
index b83a3f73819..2fa6e0cfe6f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java
@@ -73,12 +73,15 @@ public class DefaultRubyComponentService implements RubyComponentService {
public Long createComponent(String key, @Nullable String branch, String name, @Nullable String qualifier) {
// Sub view should not be created with provisioning. Will be fixed by http://jira.sonarsource.com/browse/VIEWS-296
if (!Qualifiers.SUBVIEW.equals(qualifier)) {
- String createdKey = componentService.create(NewComponent.create(key, name).setQualifier(qualifier).setBranch(branch));
- ComponentDto component = (ComponentDto) resourceDao.selectByKey(createdKey);
+ ComponentDto componentDto = componentService.create(NewComponent.create(key, name).setQualifier(qualifier).setBranch(branch));
+ if (componentDto == null) {
+ throw new BadRequestException(String.format("Component not created: %s", key));
+ }
+ ComponentDto component = (ComponentDto) resourceDao.selectByKey(componentDto.getKey());
if (component == null) {
- throw new BadRequestException(String.format("Component not created: %s", createdKey));
+ throw new BadRequestException(String.format("Component not created: %s", key));
}
- permissionService.applyDefaultPermissionTemplate(createdKey);
+ permissionService.applyDefaultPermissionTemplate(component.getKey());
return component.getId();
}
return null;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/CeQueue.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CeQueue.java
new file mode 100644
index 00000000000..4dfab3e76f5
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/CeQueue.java
@@ -0,0 +1,230 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import com.google.common.base.Optional;
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.server.computation.monitoring.CEQueueStatus;
+
+import static java.lang.String.format;
+
+/**
+ * Queue of pending Compute Engine tasks. Both producer and consumer actions
+ * are implemented.
+ * <p>
+ * This class is decoupled from the regular task type {@link org.sonar.db.ce.CeTaskTypes#REPORT}.
+ * </p>
+ */
+@ServerSide
+public class CeQueue {
+
+ private final System2 system2;
+ private final DbClient dbClient;
+ private final UuidFactory uuidFactory;
+ private final CEQueueStatus queueStatus;
+ private final CeQueueListener[] listeners;
+
+ // state
+ private boolean submitPaused = false;
+ private boolean peekPaused = false;
+
+ public CeQueue(System2 system2, DbClient dbClient, UuidFactory uuidFactory,
+ CEQueueStatus queueStatus, CeQueueListener[] listeners) {
+ this.system2 = system2;
+ this.dbClient = dbClient;
+ this.uuidFactory = uuidFactory;
+ this.queueStatus = queueStatus;
+ this.listeners = listeners;
+ }
+
+ public CeTaskSubmit prepareSubmit() {
+ return new CeTaskSubmit(uuidFactory.create());
+ }
+
+ public CeTask submit(CeTaskSubmit submit) {
+ if (submitPaused) {
+ throw new IllegalStateException("Compute Engine does not currently accept new tasks");
+ }
+ CeTask task = new CeTask(submit);
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ CeQueueDto dto = new CeQueueDto();
+ dto.setUuid(task.getUuid());
+ dto.setTaskType(task.getType());
+ dto.setComponentUuid(task.getComponentUuid());
+ dto.setStatus(CeQueueDto.Status.PENDING);
+ dto.setSubmitterLogin(task.getSubmitterLogin());
+ dto.setStartedAt(null);
+ dbClient.ceQueueDao().insert(dbSession, dto);
+ dbSession.commit();
+ queueStatus.addReceived();
+ return task;
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ public Optional<CeTask> peek() {
+ if (peekPaused) {
+ return Optional.absent();
+ }
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ Optional<CeQueueDto> dto = dbClient.ceQueueDao().peek(dbSession);
+ if (!dto.isPresent()) {
+ return Optional.absent();
+ }
+ queueStatus.addInProgress();
+ return Optional.of(new CeTask(dto.get()));
+
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ public boolean cancel(String taskUuid) {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ Optional<CeQueueDto> queueDto = dbClient.ceQueueDao().selectByUuid(dbSession, taskUuid);
+ if (queueDto.isPresent()) {
+ if (!queueDto.get().getStatus().equals(CeQueueDto.Status.PENDING)) {
+ throw new IllegalStateException(String.format("Task is in progress and can't be cancelled [uuid=%s]", taskUuid));
+ }
+ cancel(dbSession, queueDto.get());
+ return true;
+ }
+ return false;
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ void cancel(DbSession dbSession, CeQueueDto q) {
+ CeActivityDto activityDto = new CeActivityDto(q);
+ activityDto.setStatus(CeActivityDto.Status.CANCELED);
+ remove(dbSession, new CeTask(q), q, activityDto);
+ }
+
+
+ /**
+ * Removes all the tasks from the queue, whatever their status. They are marked
+ * as {@link org.sonar.db.ce.CeActivityDto.Status#CANCELED} in past activity.
+ * This method can NOT be called when workers are being executed, as in progress
+ * tasks can't be killed.
+ *
+ * @return the number of canceled tasks
+ */
+ public int clear() {
+ return cancelAll(true);
+ }
+
+ /**
+ * Similar as {@link #clear()}, except that the tasks with status
+ * {@link org.sonar.db.ce.CeQueueDto.Status#IN_PROGRESS} are ignored. This method
+ * can be called at runtime, even if workers are being executed.
+ *
+ * @return the number of canceled tasks
+ */
+ public int cancelAll() {
+ return cancelAll(false);
+ }
+
+ private int cancelAll(boolean includeInProgress) {
+ int count = 0;
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ for (CeQueueDto queueDto : dbClient.ceQueueDao().selectAllInAscOrder(dbSession)) {
+ if (includeInProgress || !queueDto.getStatus().equals(CeQueueDto.Status.IN_PROGRESS)) {
+ cancel(dbSession, queueDto);
+ count++;
+ }
+ }
+ return count;
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ public void remove(CeTask task, CeActivityDto.Status status) {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ Optional<CeQueueDto> queueDto = dbClient.ceQueueDao().selectByUuid(dbSession, task.getUuid());
+ if (!queueDto.isPresent()) {
+ throw new IllegalStateException(format("Task does not exist anymore: %s", task));
+ }
+ CeActivityDto activityDto = new CeActivityDto(queueDto.get());
+ activityDto.setStatus(status);
+ Long startedAt = activityDto.getStartedAt();
+ if (startedAt != null) {
+ activityDto.setFinishedAt(system2.now());
+ long executionTime = activityDto.getFinishedAt() - startedAt;
+ activityDto.setExecutionTimeMs(executionTime);
+ if (status == CeActivityDto.Status.SUCCESS) {
+ queueStatus.addSuccess(executionTime);
+ } else {
+ queueStatus.addError(executionTime);
+ }
+ }
+ remove(dbSession, task, queueDto.get(), activityDto);
+
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ private void remove(DbSession dbSession, CeTask task, CeQueueDto queueDto, CeActivityDto activityDto) {
+ dbClient.ceActivityDao().insert(dbSession, activityDto);
+ dbClient.ceQueueDao().deleteByUuid(dbSession, queueDto.getUuid());
+ dbSession.commit();
+ for (CeQueueListener listener : listeners) {
+ listener.onRemoved(task, activityDto.getStatus());
+ }
+ }
+
+ public void pauseSubmit() {
+ this.submitPaused = true;
+ }
+
+ public void resumeSubmit() {
+ this.submitPaused = false;
+ }
+
+ public boolean isSubmitPaused() {
+ return submitPaused;
+ }
+
+ public void pausePeek() {
+ this.peekPaused = true;
+ }
+
+ public void resumePeek() {
+ this.peekPaused = false;
+ }
+
+ public boolean isPeekPaused() {
+ return peekPaused;
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/CeQueueInitializer.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CeQueueInitializer.java
new file mode 100644
index 00000000000..661e9ba680d
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/CeQueueInitializer.java
@@ -0,0 +1,110 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.sonar.api.platform.ServerUpgradeStatus;
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.server.computation.monitoring.CEQueueStatus;
+
+/**
+ * Cleans-up the Compute Engine queue and resets the JMX counters.
+ * CE workers must not be started before execution of this class.
+ */
+@ServerSide
+public class CeQueueInitializer {
+
+ private static final Logger LOGGER = Loggers.get(CeQueueInitializer.class);
+
+ private final DbClient dbClient;
+ private final ServerUpgradeStatus serverUpgradeStatus;
+ private final ReportFiles reportFiles;
+ private final CeQueue queue;
+ private final CEQueueStatus queueStatus;
+
+ public CeQueueInitializer(DbClient dbClient, ServerUpgradeStatus serverUpgradeStatus, ReportFiles reportFiles,
+ CeQueue queue, CEQueueStatus queueStatus) {
+ this.dbClient = dbClient;
+ this.serverUpgradeStatus = serverUpgradeStatus;
+ this.reportFiles = reportFiles;
+ this.queue = queue;
+ this.queueStatus = queueStatus;
+ }
+
+ /**
+ * Do not rename. Used at server startup.
+ */
+ public void start() {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ initJmxCounters(dbSession);
+
+ if (serverUpgradeStatus.isUpgraded()) {
+ cleanOnUpgrade();
+ } else {
+ verifyConsistency(dbSession);
+ }
+
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ private void cleanOnUpgrade() {
+ // we assume that pending tasks are not compatible with the new version
+ // and can't be processed
+ LOGGER.info("Cancel all pending tasks (due to upgrade)");
+ queue.clear();
+ }
+
+ private void verifyConsistency(DbSession dbSession) {
+ // server is not being upgraded
+ dbClient.ceQueueDao().resetAllToPendingStatus(dbSession);
+ dbSession.commit();
+
+ // verify that the report files are available for the tasks in queue
+ Set<String> uuidsInQueue = new HashSet<>();
+ for (CeQueueDto queueDto : dbClient.ceQueueDao().selectAllInAscOrder(dbSession)) {
+ uuidsInQueue.add(queueDto.getUuid());
+ if (CeTaskTypes.REPORT.equals(queueDto.getTaskType()) && !reportFiles.fileForUuid(queueDto.getUuid()).exists()) {
+ // the report is not available on file system
+ queue.cancel(dbSession, queueDto);
+ }
+ }
+
+ // clean-up filesystem
+ for (String uuid : reportFiles.listUuids()) {
+ if (!uuidsInQueue.contains(uuid)) {
+ reportFiles.deleteIfExists(uuid);
+ }
+ }
+ }
+
+ private void initJmxCounters(DbSession dbSession) {
+ queueStatus.initPendingCount(dbClient.ceQueueDao().countAll(dbSession));
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/activity/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CeQueueListener.java
index 84449c529aa..420c660dd70 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/activity/package-info.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/CeQueueListener.java
@@ -17,8 +17,12 @@
* 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;
-@ParametersAreNonnullByDefault
-package org.sonar.server.computation.activity;
+import org.sonar.db.ce.CeActivityDto;
-import javax.annotation.ParametersAreNonnullByDefault;
+public interface CeQueueListener {
+
+ void onRemoved(CeTask task, CeActivityDto.Status status);
+
+}
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..38284022f10
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/CeTask.java
@@ -0,0 +1,101 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import com.google.common.base.Objects;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.db.ce.CeQueueDto;
+
+@Immutable
+public class CeTask {
+
+ private final String type;
+ private final String uuid;
+ private final String componentUuid;
+ private final String submitterLogin;
+
+ public CeTask(String uuid, String type, @Nullable String componentUuid, @Nullable String submitterLogin) {
+ this.uuid = uuid;
+ this.type = type;
+ this.componentUuid = componentUuid;
+ this.submitterLogin = submitterLogin;
+ }
+
+ CeTask(CeTaskSubmit submit) {
+ this.uuid = submit.getUuid();
+ this.type = submit.getType();
+ this.componentUuid = submit.getComponentUuid();
+ this.submitterLogin = submit.getSubmitterLogin();
+ }
+
+ CeTask(CeQueueDto dto) {
+ this.uuid = dto.getUuid();
+ this.type = dto.getTaskType();
+ this.componentUuid = dto.getComponentUuid();
+ this.submitterLogin = dto.getSubmitterLogin();
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ @CheckForNull
+ public String getComponentUuid() {
+ return componentUuid;
+ }
+
+ @CheckForNull
+ public String getSubmitterLogin() {
+ return submitterLogin;
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .add("componentUuid", componentUuid)
+ .add("uuid", uuid)
+ .add("type", type)
+ .add("submitterLogin", submitterLogin)
+ .toString();
+ }
+
+ @Override
+ public boolean equals(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();
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueCleanerTest.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CeTaskSubmit.java
index 38a587590c3..ab2c2513005 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueCleanerTest.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/CeTaskSubmit.java
@@ -17,32 +17,44 @@
* 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.Test;
-import org.sonar.api.platform.ServerUpgradeStatus;
+public class CeTaskSubmit {
+
+ private final String uuid;
+ private String type;
+ private String componentUuid;
+ private String submitterLogin;
+
+ CeTaskSubmit(String uuid) {
+ this.uuid = uuid;
+ }
-import static org.mockito.Mockito.*;
+ public String getUuid() {
+ return uuid;
+ }
-public class ReportQueueCleanerTest {
+ public String getType() {
+ return type;
+ }
- ServerUpgradeStatus serverUpgradeStatus = mock(ServerUpgradeStatus.class);
- ReportQueue queue = mock(ReportQueue.class);
- ReportQueueCleaner underTest = new ReportQueueCleaner(serverUpgradeStatus, queue);
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getComponentUuid() {
+ return componentUuid;
+ }
+
+ public void setComponentUuid(String s) {
+ this.componentUuid = s;
+ }
- @Test
- public void reset_reports_on_restart() {
- underTest.start();
- verify(queue).resetToPendingStatus();
- underTest.stop();
+ public String getSubmitterLogin() {
+ return submitterLogin;
}
- @Test
- public void delete_all_reports_on_upgrade() {
- when(serverUpgradeStatus.isUpgraded()).thenReturn(Boolean.TRUE);
- underTest.start();
- verify(queue).clear();
- underTest.stop();
+ public void setSubmitterLogin(String s) {
+ this.submitterLogin = s;
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineTask.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CeWorker.java
index 626c11b207f..f3cf7df966f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineTask.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/CeWorker.java
@@ -20,7 +20,7 @@
package org.sonar.server.computation;
/**
- * A task to be executed by the Compute Engine.
+ * Worker that executes the tasks got from the queue
*/
-public interface ComputeEngineTask extends Runnable {
+public interface CeWorker extends Runnable {
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/CeWorkerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CeWorkerImpl.java
new file mode 100644
index 00000000000..3e2f8d29be1
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/CeWorkerImpl.java
@@ -0,0 +1,66 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.computation;
+
+import com.google.common.base.Optional;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.core.util.logs.Profiler;
+import org.sonar.db.ce.CeActivityDto;
+
+public class CeWorkerImpl implements CeWorker {
+
+ private static final Logger LOG = Loggers.get(CeWorkerImpl.class);
+
+ private final CeQueue queue;
+ private final ReportTaskProcessor reportTaskProcessor;
+
+ public CeWorkerImpl(CeQueue queue, ReportTaskProcessor reportTaskProcessor) {
+ this.queue = queue;
+ this.reportTaskProcessor = reportTaskProcessor;
+ }
+
+ @Override
+ public void run() {
+ Profiler profiler = Profiler.create(LOG).start();
+ CeTask task;
+ try {
+ Optional<CeTask> taskOpt = queue.peek();
+ if (!taskOpt.isPresent()) {
+ return;
+ }
+ task = taskOpt.get();
+ } catch (Exception e) {
+ LOG.error("Failed to pop the queue of analysis reports", e);
+ return;
+ }
+
+ try {
+ reportTaskProcessor.process(task);
+ queue.remove(task, CeActivityDto.Status.SUCCESS);
+ } catch (Throwable e) {
+ LOG.error(String.format("Failed to process task %s", task.getUuid()), e);
+ queue.remove(task, CeActivityDto.Status.FAILED);
+ } finally {
+ profiler.stopInfo(String.format("Total thread execution of project %s (report %s)", task.getComponentUuid(), task.getUuid()));
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/CleanReportQueueListener.java b/server/sonar-server/src/main/java/org/sonar/server/computation/CleanReportQueueListener.java
new file mode 100644
index 00000000000..16a793ea6a1
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/CleanReportQueueListener.java
@@ -0,0 +1,36 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import org.sonar.db.ce.CeActivityDto;
+
+public class CleanReportQueueListener implements CeQueueListener {
+
+ private final ReportFiles reportFiles;
+
+ public CleanReportQueueListener(ReportFiles reportFiles) {
+ this.reportFiles = reportFiles;
+ }
+
+ @Override
+ public void onRemoved(CeTask task, CeActivityDto.Status status) {
+ reportFiles.deleteIfExists(task.getUuid());
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationStepExecutor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationStepExecutor.java
index c90f2a75f7f..8fb79cce6e4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationStepExecutor.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationStepExecutor.java
@@ -20,79 +20,26 @@
package org.sonar.server.computation;
import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.core.util.logs.Profiler;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
import org.sonar.server.computation.step.ComputationStep;
-
-import static java.lang.String.format;
-import static java.util.Objects.requireNonNull;
+import org.sonar.server.computation.step.ComputationSteps;
public final class ComputationStepExecutor {
- private final Logger logger;
- private final Listener listener;
- private final String description;
- private final CEQueueStatus queueStatus;
-
- public ComputationStepExecutor(Logger logger, Listener listener, String description, CEQueueStatus queueStatus) {
- this.logger = requireNonNull(logger);
- this.listener = requireNonNull(listener);
- this.description = requireNonNull(description);
- this.queueStatus = queueStatus;
- }
+ private static final Logger LOGGER = Loggers.get(ComputationStepExecutor.class);
- public void execute(Iterable<ComputationStep> steps) {
- queueStatus.addInProgress();
- listener.onStart();
- Profiler profiler = Profiler.create(logger).startDebug(description);
- long timingSum = 0L;
- Profiler stepProfiler = Profiler.create(logger);
- try {
- for (ComputationStep step : steps) {
- stepProfiler.start();
- step.execute();
- timingSum += stepProfiler.stopInfo(step.getDescription());
- }
- long timing = logProcessingEnd(description, profiler, timingSum);
- queueStatus.addSuccess(timing);
- listener.onSuccess(timing);
- } catch (Throwable e) {
- long timing = logProcessingEnd(description, profiler, timingSum);
- queueStatus.addError(timing);
- listener.onError(e, timing);
- } finally {
- listener.onEnd();
- }
- }
+ private final ComputationSteps steps;
- private static long logProcessingEnd(String message, Profiler profiler, long timingSum) {
- return profiler.stopInfo(format("%s total time spent in steps=%sms", message, timingSum));
+ public ComputationStepExecutor(ComputationSteps steps) {
+ this.steps = steps;
}
- public interface Listener {
-
- /**
- * Called before the first ComputationStep is executed.
- */
- void onStart();
-
- /**
- * Called when on ComputationSteps have been executed and no error occurred.
- *
- * @param timing the duration of the execution
- */
- void onSuccess(long timing);
-
- /**
- * Called when on ComputationSteps have been executed and no error occurred.
- *
- * @param e the error
- * @param timing the duration of the execution
- */
- void onError(Throwable e, long timing);
-
- /**
- * Called when all ComputationSteps have been executed, after either {@link #onSuccess(long)} or {@link #onError(Throwable, long)}
- */
- void onEnd();
+ public void execute() {
+ Profiler stepProfiler = Profiler.create(LOGGER);
+ for (ComputationStep step : steps.instances()) {
+ stepProfiler.start();
+ step.execute();
+ stepProfiler.stopInfo(step.getDescription());
+ }
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingExecutorService.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingExecutorService.java
index 1c3fea8fd8d..f6075d569f8 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingExecutorService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingExecutorService.java
@@ -22,7 +22,7 @@ package org.sonar.server.computation;
import org.sonar.server.util.StoppableScheduledExecutorService;
/**
- * The {@link java.util.concurrent.ExecutorService} responsible for running {@link ComputeEngineTask}.
+ * The {@link java.util.concurrent.ExecutorService} responsible for running {@link CeWorker}.
*/
public interface ComputeEngineProcessingExecutorService extends StoppableScheduledExecutorService {
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingModule.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingModule.java
index c48cb432f7d..ea1d40a72a0 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingModule.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingModule.java
@@ -20,11 +20,16 @@
package org.sonar.server.computation;
import org.sonar.core.platform.Module;
+import org.sonar.server.computation.container.ContainerFactoryImpl;
public class ComputeEngineProcessingModule extends Module {
@Override
protected void configureModule() {
add(
+ CeWorkerImpl.class,
+ ContainerFactoryImpl.class,
+ ComputationStepExecutor.class,
+ ReportTaskProcessor.class,
ReportProcessingScheduler.class,
ReportProcessingSchedulerExecutorServiceImpl.class,
ComputeEngineProcessingExecutorServiceImpl.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingQueue.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingQueue.java
index 687aca20c59..5bef453b115 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingQueue.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingQueue.java
@@ -23,5 +23,5 @@ public interface ComputeEngineProcessingQueue {
/**
* Adds a task to the Compute Engine processing queue.
*/
- void addTask(ComputeEngineTask task);
+ void addTask(CeWorker task);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingQueueImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingQueueImpl.java
index b981002ca30..69805c00c4f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingQueueImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputeEngineProcessingQueueImpl.java
@@ -33,7 +33,7 @@ public class ComputeEngineProcessingQueueImpl implements ComputeEngineProcessing
private static final Logger LOG = Loggers.get(ComputeEngineProcessingQueueImpl.class);
private final ComputeEngineProcessingExecutorService processingService;
- private final ConcurrentLinkedQueue<ComputeEngineTask> queue = Queues.newConcurrentLinkedQueue();
+ private final ConcurrentLinkedQueue<CeWorker> queue = Queues.newConcurrentLinkedQueue();
private final long delayBetweenTasks;
private final long delayForFirstStart;
@@ -48,7 +48,7 @@ public class ComputeEngineProcessingQueueImpl implements ComputeEngineProcessing
}
@Override
- public void addTask(ComputeEngineTask task) {
+ public void addTask(CeWorker task) {
requireNonNull(task, "a ComputeEngineTask can not be null");
queue.add(task);
@@ -62,7 +62,7 @@ public class ComputeEngineProcessingQueueImpl implements ComputeEngineProcessing
private class ProcessHeadOfQueueRunnable implements Runnable {
@Override
public void run() {
- ComputeEngineTask task = queue.poll();
+ CeWorker task = queue.poll();
if (task != null) {
try {
task.run();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportFiles.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportFiles.java
new file mode 100644
index 00000000000..6b24dafdff9
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportFiles.java
@@ -0,0 +1,95 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.config.Settings;
+import org.sonar.api.server.ServerSide;
+import org.sonar.process.ProcessProperties;
+
+import static java.lang.String.format;
+
+// TODO deal with temporary unzipped files
+@ServerSide
+public class ReportFiles {
+
+ private static final String ZIP_EXTENSION = "zip";
+
+ private final Settings settings;
+
+ public ReportFiles(Settings settings) {
+ this.settings = settings;
+ }
+
+ public void save(CeTaskSubmit taskSubmit, InputStream reportInput) {
+ File file = fileForUuid(taskSubmit.getUuid());
+ try {
+ FileUtils.copyInputStreamToFile(reportInput, file);
+ } catch (Exception e) {
+ FileUtils.deleteQuietly(file);
+ IOUtils.closeQuietly(reportInput);
+ throw new IllegalStateException(format("Fail to copy report to file: %s", file.getAbsolutePath()), e);
+ }
+ }
+
+ public void deleteIfExists(String taskUuid) {
+ FileUtils.deleteQuietly(fileForUuid(taskUuid));
+ }
+
+ public void deleteAll() {
+ File dir = reportDir();
+ try {
+ FileUtils.deleteDirectory(dir);
+ } catch (Exception e) {
+ throw new IllegalStateException(format("Fail to delete directory: %s", dir.getAbsolutePath()), e);
+ }
+ }
+
+ private File reportDir() {
+ return new File(settings.getString(ProcessProperties.PATH_DATA), "ce/reports");
+ }
+
+ /**
+ * The analysis report to be processed. Can't be null
+ * but may no exist on file system.
+ */
+ public File fileForUuid(String taskUuid) {
+ return new File(reportDir(), format("%s.%s", taskUuid, ZIP_EXTENSION));
+ }
+
+ public List<String> listUuids() {
+ List<String> uuids = new ArrayList<>();
+ File dir = reportDir();
+ if (dir.exists()) {
+ Collection<File> files = FileUtils.listFiles(dir, new String[]{ZIP_EXTENSION}, false);
+ for (File file : files) {
+ uuids.add(FilenameUtils.getBaseName(file.getName()));
+ }
+ }
+ return uuids;
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingScheduler.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingScheduler.java
index 7bc833ff734..89c472b813a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingScheduler.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingScheduler.java
@@ -23,23 +23,14 @@ package org.sonar.server.computation;
import java.util.concurrent.TimeUnit;
import org.sonar.api.platform.Server;
import org.sonar.api.platform.ServerStartHandler;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.container.ContainerFactory;
-import org.sonar.server.computation.container.ContainerFactoryImpl;
/**
* Adds tasks to the Compute Engine to process batch reports.
*/
public class ReportProcessingScheduler implements ServerStartHandler {
- private static final Logger LOG = Loggers.get(ReportProcessingScheduler.class);
-
private final ReportProcessingSchedulerExecutorService reportProcessingSchedulerExecutorService;
private final ComputeEngineProcessingQueue processingQueue;
- private final ReportQueue queue;
- private final ComponentContainer sqContainer;
- private final ContainerFactory containerFactory;
+ private final CeWorker worker;
private final long delayBetweenTasks;
private final long delayForFirstStart;
@@ -47,12 +38,10 @@ public class ReportProcessingScheduler implements ServerStartHandler {
public ReportProcessingScheduler(ReportProcessingSchedulerExecutorService reportProcessingSchedulerExecutorService,
ComputeEngineProcessingQueue processingQueue,
- ReportQueue queue, ComponentContainer sqContainer) {
+ CeWorker worker) {
this.reportProcessingSchedulerExecutorService = reportProcessingSchedulerExecutorService;
this.processingQueue = processingQueue;
- this.queue = queue;
- this.sqContainer = sqContainer;
- this.containerFactory = new ContainerFactoryImpl();
+ this.worker = worker;
this.delayBetweenTasks = 10;
this.delayForFirstStart = 0;
@@ -71,14 +60,7 @@ public class ReportProcessingScheduler implements ServerStartHandler {
private class AddReportProcessingToCEProcessingQueue implements Runnable {
@Override
public void run() {
- try {
- ReportQueue.Item item = queue.pop();
- if (item != null) {
- processingQueue.addTask(new ReportProcessingTask(queue, item, sqContainer, containerFactory));
- }
- } catch (Exception e) {
- LOG.error("Failed to pop the queue of analysis reports", e);
- }
+ processingQueue.addTask(worker);
}
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingSchedulerExecutorService.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingSchedulerExecutorService.java
index 806cfd9a791..fb9ecd57618 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingSchedulerExecutorService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingSchedulerExecutorService.java
@@ -22,7 +22,7 @@ package org.sonar.server.computation;
import org.sonar.server.util.StoppableScheduledExecutorService;
/**
- * ExecutorService responsible for adding {@link ReportProcessingTask} to {@link ReportQueue} on a regular basis.
+ * ExecutorService responsible for adding {@link CeWorkerImpl} to {@link CeQueue} on a regular basis.
*/
public interface ReportProcessingSchedulerExecutorService extends StoppableScheduledExecutorService {
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingTask.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingTask.java
deleted file mode 100644
index 4b6b68b8312..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessingTask.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation;
-
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.platform.ComponentContainer;
-import org.sonar.core.util.logs.Profiler;
-import org.sonar.server.computation.container.ComputeEngineContainer;
-import org.sonar.server.computation.container.ContainerFactory;
-
-/**
- * This Compute E pops a report from the queue and integrate it.
- */
-public class ReportProcessingTask implements ComputeEngineTask {
-
- private static final Logger LOG = Loggers.get(ReportProcessingTask.class);
-
- private final ReportQueue queue;
- private final ReportQueue.Item item;
- private final ComponentContainer sqContainer;
- private final ContainerFactory containerFactory;
-
- public ReportProcessingTask(ReportQueue queue, ReportQueue.Item item, ComponentContainer sqContainer, ContainerFactory containerFactory) {
- this.queue = queue;
- this.item = item;
- this.sqContainer = sqContainer;
- this.containerFactory = containerFactory;
- }
-
- @Override
- public void run() {
- Profiler profiler = Profiler.create(LOG).start();
-
- ComputeEngineContainer computeEngineContainer = containerFactory.create(sqContainer, item);
- try {
- computeEngineContainer.getComponentByType(ReportProcessor.class).process();
- } catch (Throwable e) {
- LOG.error(String.format(
- "Failed to process analysis report %d of project %s", item.dto.getId(), item.dto.getProjectKey()), e);
- } finally {
- computeEngineContainer.cleanup();
-
- removeSilentlyFromQueue(item);
- }
- profiler.stopInfo(String.format("Total thread execution of project %s (report %d)", item.dto.getProjectKey(), item.dto.getId()));
- }
-
- private void removeSilentlyFromQueue(ReportQueue.Item item) {
- try {
- queue.remove(item);
- } catch (Exception e) {
- LOG.error(String.format("Failed to remove analysis report %d from queue", item.dto.getId()), e);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessor.java
deleted file mode 100644
index 958cbae3d2d..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportProcessor.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation;
-
-import com.google.common.base.Throwables;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.computation.activity.ActivityManager;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
-import org.sonar.server.computation.step.ComputationSteps;
-
-import static java.lang.String.format;
-import static org.sonar.db.compute.AnalysisReportDto.Status.FAILED;
-import static org.sonar.db.compute.AnalysisReportDto.Status.SUCCESS;
-
-public class ReportProcessor {
-
- private final ComputationStepExecutor executor;
- private final ComputationSteps steps;
-
- public ReportProcessor(ComputationSteps steps,
- ReportQueue.Item item, ActivityManager activityManager, System2 system, CEQueueStatus queueStatus) {
- this.executor = new ComputationStepExecutor(
- Loggers.get(ReportProcessor.class),
- new ReportProcessingStepsExecutorListener(item, system, activityManager, queueStatus),
- createDescription(item), queueStatus);
- this.steps = steps;
- }
-
- public void process() {
- this.executor.execute(this.steps.instances());
- }
-
- private static String createDescription(ReportQueue.Item item) {
- String projectKey = item.dto.getProjectKey();
- return format("Analysis of project %s (report %d)", projectKey, item.dto.getId());
- }
-
- private static class ReportProcessingStepsExecutorListener implements ComputationStepExecutor.Listener {
- private final ReportQueue.Item item;
- private final System2 system;
- private final ActivityManager activityManager;
-
- private ReportProcessingStepsExecutorListener(ReportQueue.Item item, System2 system, ActivityManager activityManager, CEQueueStatus queueStatus) {
- this.item = item;
- this.system = system;
- this.activityManager = activityManager;
- }
-
- @Override
- public void onStart() {
- // nothing to do on start
- }
-
- @Override
- public void onSuccess(long timing) {
- item.dto.setStatus(SUCCESS);
- }
-
- @Override
- public void onError(Throwable e, long timing) {
- item.dto.setStatus(FAILED);
- throw Throwables.propagate(e);
- }
-
- @Override
- public void onEnd() {
- item.dto.setFinishedAt(system.now());
- activityManager.saveActivity(item.dto);
- }
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java
deleted file mode 100644
index 5a0607b5c50..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueue.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-import javax.annotation.CheckForNull;
-import org.apache.commons.io.FileUtils;
-import org.sonar.api.config.Settings;
-import org.sonar.api.server.ServerSide;
-import org.sonar.core.util.Uuids;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.MyBatis;
-import org.sonar.db.compute.AnalysisReportDao;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.process.ProcessProperties;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
-
-import static org.sonar.db.compute.AnalysisReportDto.Status.PENDING;
-
-@ServerSide
-public class ReportQueue {
- private final DbClient dbClient;
- private final Settings settings;
- private final CEQueueStatus queueStatus;
-
- public ReportQueue(DbClient dbClient, Settings settings, CEQueueStatus queueStatus) {
- this.dbClient = dbClient;
- this.settings = settings;
- this.queueStatus = queueStatus;
- }
-
- public void start() {
- DbSession session = dbClient.openSession(false);
- try {
- queueStatus.initPendingCount(dao().countPending(session));
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
- public Item add(String projectKey, String projectName, InputStream reportData) {
- String uuid = Uuids.create();
- File file = reportFileForUuid(uuid);
-
- DbSession session = dbClient.openSession(false);
- try {
- saveReportOnDisk(reportData, file);
- AnalysisReportDto dto = saveReportMetadataInDatabase(projectKey, projectName, uuid, session);
-
- return new Item(dto, file);
- } catch (Exception e) {
- FileUtils.deleteQuietly(file);
- throw new IllegalStateException("Fail to store analysis report of project " + projectKey, e);
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
- private AnalysisReportDto saveReportMetadataInDatabase(String projectKey, String projectName, String uuid, DbSession session) {
- AnalysisReportDto dto = new AnalysisReportDto()
- .setProjectKey(projectKey)
- .setProjectName(projectName)
- .setStatus(PENDING)
- .setUuid(uuid);
- dao().insert(session, dto);
- session.commit();
- return dto;
- }
-
- private AnalysisReportDao dao() {
- return dbClient.analysisReportDao();
- }
-
- private static void saveReportOnDisk(InputStream reportData, File file) throws IOException {
- FileUtils.copyInputStreamToFile(reportData, file);
- }
-
- public void remove(Item item) {
- DbSession session = dbClient.openSession(false);
- try {
- FileUtils.deleteQuietly(item.zipFile);
- dao().delete(session, item.dto.getId());
- session.commit();
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
- @CheckForNull
- public Item pop() {
- DbSession session = dbClient.openSession(false);
- try {
- AnalysisReportDto dto = dao().pop(session);
- if (dto != null) {
- File file = reportFileForUuid(dto.getUuid());
- if (file.exists()) {
- return new Item(dto, file);
- }
- Loggers.get(getClass()).error("Analysis report not found: " + file.getAbsolutePath());
- dao().delete(session, dto.getId());
- session.commit();
- }
- return null;
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
- /**
- * Truncates table ANALYSIS_REPORTS and delete all files from directory {data}/analysis
- */
- public void clear() {
- File dir = reportsDir();
- try {
- FileUtils.deleteDirectory(dir);
- } catch (IOException e) {
- throw new IllegalStateException("Fail to delete directory: " + dir.getAbsolutePath(), e);
- }
-
- DbSession session = dbClient.openSession(false);
- try {
- dao().truncate(session);
- session.commit();
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
- public void resetToPendingStatus() {
- DbSession session = dbClient.openSession(false);
- try {
- dao().resetAllToPendingStatus(session);
- session.commit();
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
- /**
- * All the reports of the queue, whatever the status
- */
- public List<AnalysisReportDto> all() {
- DbSession session = dbClient.openSession(false);
- try {
- return dao().selectAll(session);
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
- /**
- * This directory is a flat list of the reports referenced in table ANALYSIS_REPORTS.
- * Never return null but the directory may not exist.
- */
- private File reportsDir() {
- return new File(settings.getString(ProcessProperties.PATH_DATA), "analysis");
- }
-
- private File reportFileForUuid(String uuid) {
- return new File(reportsDir(), String.format("%s.zip", uuid));
- }
-
- public static class Item {
- public final AnalysisReportDto dto;
- public final File zipFile;
-
- public Item(AnalysisReportDto dto, File zipFile) {
- this.dto = dto;
- this.zipFile = zipFile;
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueueCleaner.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueueCleaner.java
deleted file mode 100644
index fb82118ccd8..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportQueueCleaner.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation;
-
-import org.picocontainer.Startable;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.platform.ServerUpgradeStatus;
-
-/**
- * Clean-up queue of reports at server startup:
- * <ul>
- * <li>remove all reports if server being upgraded to a new version (we assume that
- * format of reports is not forward-compatible)</li>
- * <li>reset reports that were in status WORKING while server stopped</li>
- * </ul>
- */
-@ServerSide
-public class ReportQueueCleaner implements Startable {
-
- private final ServerUpgradeStatus serverUpgradeStatus;
- private final ReportQueue queue;
-
- public ReportQueueCleaner(ServerUpgradeStatus serverUpgradeStatus, ReportQueue queue) {
- this.serverUpgradeStatus = serverUpgradeStatus;
- this.queue = queue;
- }
-
- @Override
- public void start() {
- if (serverUpgradeStatus.isUpgraded()) {
- queue.clear();
- } else {
- queue.resetToPendingStatus();
- }
- }
-
- @Override
- public void stop() {
- // do nothing
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportSubmitter.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportSubmitter.java
new file mode 100644
index 00000000000..1fe382e9b51
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportSubmitter.java
@@ -0,0 +1,71 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import java.io.InputStream;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.server.ServerSide;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.component.ComponentService;
+import org.sonar.server.component.NewComponent;
+import org.sonar.server.user.UserSession;
+
+@ServerSide
+public class ReportSubmitter {
+
+ private final CeQueue queue;
+ private final UserSession userSession;
+ private final ReportFiles reportFiles;
+ private final ComponentService componentService;
+
+ public ReportSubmitter(CeQueue queue, UserSession userSession, ReportFiles reportFiles,
+ ComponentService componentService) {
+ this.queue = queue;
+ this.userSession = userSession;
+ this.reportFiles = reportFiles;
+ this.componentService = componentService;
+ }
+
+ public CeTask submit(String projectKey, @Nullable String projectName, InputStream reportInput) {
+ userSession.checkGlobalPermission(GlobalPermissions.SCAN_EXECUTION);
+
+ ComponentDto project = componentService.getNullableByKey(projectKey);
+ if (project == null) {
+ // the project does not exist -> requires to provision it
+ NewComponent newProject = new NewComponent(projectKey, StringUtils.defaultIfBlank(projectName, projectKey));
+ newProject.setQualifier(Qualifiers.PROJECT);
+ // no need to verify the permission "provisionning" as it's already handled by componentService
+ project = componentService.create(newProject);
+ }
+
+ // the report file must be saved before submitting the task
+ CeTaskSubmit submit = queue.prepareSubmit();
+ reportFiles.save(submit, reportInput);
+
+ submit.setType(CeTaskTypes.REPORT);
+ submit.setComponentUuid(project.uuid());
+ submit.setSubmitterLogin(userSession.getLogin());
+ return queue.submit(submit);
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ReportTaskProcessor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportTaskProcessor.java
new file mode 100644
index 00000000000..e8dc5803bde
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ReportTaskProcessor.java
@@ -0,0 +1,44 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.server.computation.container.ComputeEngineContainer;
+import org.sonar.server.computation.container.ContainerFactory;
+
+public class ReportTaskProcessor {
+
+ private final ContainerFactory containerFactory;
+ private final ComponentContainer serverContainer;
+
+ public ReportTaskProcessor(ContainerFactory containerFactory, ComponentContainer serverContainer) {
+ this.containerFactory = containerFactory;
+ this.serverContainer = serverContainer;
+ }
+
+ public void process(CeTask task) {
+ ComputeEngineContainer ceContainer = containerFactory.create(serverContainer, task);
+ try {
+ ceContainer.getComponentByType(ComputationStepExecutor.class).execute();
+ } finally {
+ ceContainer.cleanup();
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/activity/ActivityManager.java b/server/sonar-server/src/main/java/org/sonar/server/computation/activity/ActivityManager.java
deleted file mode 100644
index 7df6ff1cf80..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/activity/ActivityManager.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation.activity;
-
-import com.google.common.base.Optional;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.MyBatis;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.server.activity.Activity;
-import org.sonar.server.activity.ActivityService;
-
-import static org.sonar.api.utils.DateUtils.formatDateTimeNullSafe;
-import static org.sonar.api.utils.DateUtils.longToDate;
-
-public class ActivityManager {
- private final ActivityService activityService;
- private final DbClient dbClient;
-
- public ActivityManager(ActivityService activityService, DbClient dbClient) {
- this.activityService = activityService;
- this.dbClient = dbClient;
- }
-
- public void saveActivity(AnalysisReportDto report) {
- Optional<ComponentDto> projectOptional = loadProject(report.getProjectKey());
- Activity activity = new Activity();
- activity.setType(Activity.Type.ANALYSIS_REPORT);
- activity.setAction("LOG_ANALYSIS_REPORT");
- activity
- .setData("key", String.valueOf(report.getId()))
- .setData("projectKey", report.getProjectKey())
- .setData("status", String.valueOf(report.getStatus()))
- .setData("submittedAt", formatDateTimeNullSafe(longToDate(report.getCreatedAt())))
- .setData("startedAt", formatDateTimeNullSafe(longToDate(report.getStartedAt())))
- .setData("finishedAt", formatDateTimeNullSafe(longToDate(report.getFinishedAt())));
- if (projectOptional.isPresent()) {
- ComponentDto project = projectOptional.get();
- activity
- .setData("projectName", project.name())
- .setData("projectUuid", project.uuid());
- }
- activityService.save(activity);
- }
-
- private Optional<ComponentDto> loadProject(String projectKey) {
- DbSession session = dbClient.openSession(false);
- try {
- return dbClient.componentDao().selectByKey(session, projectKey);
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportDirectoryHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportDirectoryHolder.java
index 088dbc56e71..bb76947dbda 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportDirectoryHolder.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportDirectoryHolder.java
@@ -20,11 +20,10 @@
package org.sonar.server.computation.batch;
import java.io.File;
-import org.sonar.server.computation.ReportQueue;
public interface BatchReportDirectoryHolder {
/**
- * The File of the directory where the Batch report files for the current {@link ReportQueue.Item} are stored.
+ * The File of the directory where the Batch report files for the current {@link org.sonar.server.computation.CeTask} are stored.
*
* @throws IllegalStateException if the holder is empty (ie. there is no directory yet)
*/
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportDirectoryHolderImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportDirectoryHolderImpl.java
index e6e3556393b..f0b4bba8d19 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportDirectoryHolderImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportDirectoryHolderImpl.java
@@ -23,6 +23,7 @@ import java.io.File;
import java.util.Objects;
public class BatchReportDirectoryHolderImpl implements MutableBatchReportDirectoryHolder {
+
private File directory;
@Override
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainer.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainer.java
index 4854b389fdd..87c091348ab 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainer.java
@@ -21,17 +21,16 @@ package org.sonar.server.computation.container;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.ContainerPopulator;
-import org.sonar.server.computation.ReportQueue.Item;
/**
- * The Compute Engine container. Created for a specific parent {@link ComponentContainer} and a specific {@link Item}.
+ * The Compute Engine container. Created for a specific parent {@link ComponentContainer} and a specific {@link org.sonar.server.computation.CeTask}.
*/
public interface ComputeEngineContainer extends ContainerPopulator.Container {
ComponentContainer getParent();
/**
- * Clean's up resources after process has been called and has returned.
+ * Cleans up resources after process has been called and has returned.
*/
void cleanup();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ContainerFactory.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ContainerFactory.java
index 7787a6c69e6..c1011f6969f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ContainerFactory.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ContainerFactory.java
@@ -20,12 +20,12 @@
package org.sonar.server.computation.container;
import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.CeTask;
/**
* Compute
*/
public interface ContainerFactory {
- ComputeEngineContainer create(ComponentContainer parent, ReportQueue.Item item);
+ ComputeEngineContainer create(ComponentContainer parent, CeTask task);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ContainerFactoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ContainerFactoryImpl.java
index 90c0294b8b1..ed41a1c1f11 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ContainerFactoryImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ContainerFactoryImpl.java
@@ -20,11 +20,11 @@
package org.sonar.server.computation.container;
import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.CeTask;
public class ContainerFactoryImpl implements ContainerFactory {
@Override
- public ComputeEngineContainer create(ComponentContainer parent, ReportQueue.Item item) {
- return new ComputeEngineContainerImpl(parent, new ReportComputeEngineContainerPopulator(item));
+ public ComputeEngineContainer create(ComponentContainer parent, CeTask task) {
+ return new ComputeEngineContainerImpl(parent, new ReportComputeEngineContainerPopulator(task));
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java
index 0756e92821c..453aef13d87 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java
@@ -23,10 +23,9 @@ import java.util.Arrays;
import java.util.List;
import org.sonar.core.issue.tracking.Tracker;
import org.sonar.core.platform.ContainerPopulator;
+import org.sonar.server.computation.CeTask;
import org.sonar.server.computation.ComputationTempFolderProvider;
-import org.sonar.server.computation.ReportProcessor;
-import org.sonar.server.computation.ReportQueue;
-import org.sonar.server.computation.activity.ActivityManager;
+import org.sonar.server.computation.ComputationStepExecutor;
import org.sonar.server.computation.analysis.ReportAnalysisMetadataHolder;
import org.sonar.server.computation.batch.BatchReportDirectoryHolderImpl;
import org.sonar.server.computation.batch.BatchReportReaderImpl;
@@ -85,16 +84,16 @@ import org.sonar.server.computation.step.ReportComputationSteps;
import org.sonar.server.view.index.ViewIndex;
public final class ReportComputeEngineContainerPopulator implements ContainerPopulator<ComputeEngineContainer> {
- private final ReportQueue.Item item;
+ private final CeTask task;
- public ReportComputeEngineContainerPopulator(ReportQueue.Item item) {
- this.item = item;
+ public ReportComputeEngineContainerPopulator(CeTask task) {
+ this.task = task;
}
@Override
public void populateContainer(ComputeEngineContainer container) {
ComputationSteps steps = new ReportComputationSteps(container);
- container.add(item);
+ container.add(task);
container.add(steps);
container.addSingletons(componentClasses());
container.addSingletons(steps.orderedStepClasses());
@@ -106,85 +105,80 @@ public final class ReportComputeEngineContainerPopulator implements ContainerPop
*/
private static List componentClasses() {
return Arrays.asList(
- new ComputationTempFolderProvider(),
-
- ActivityManager.class,
-
- MetricModule.class,
-
- // holders
- ReportAnalysisMetadataHolder.class,
- BatchReportDirectoryHolderImpl.class,
- ReportTreeRootHolderImpl.class,
- PeriodsHolderImpl.class,
- QualityGateHolderImpl.class,
- DebtModelHolderImpl.class,
- SqaleRatingSettings.class,
- ActiveRulesHolderImpl.class,
- MeasureComputersHolderImpl.class,
-
- BatchReportReaderImpl.class,
-
- // repositories
- LanguageRepositoryImpl.class,
- MeasureRepositoryImpl.class,
- EventRepositoryImpl.class,
- SettingsRepositoryImpl.class,
- DbIdsRepositoryImpl.class,
- QualityGateServiceImpl.class,
- EvaluationResultTextConverterImpl.class,
-
- // issues
- RuleCacheLoader.class,
- RuleRepositoryImpl.class,
- ScmAccountToUserLoader.class,
- ScmAccountToUser.class,
- IssueCache.class,
- DefaultAssignee.class,
- IssueVisitors.class,
- IssueLifecycle.class,
- ComponentsWithUnprocessedIssues.class,
- ComponentIssuesRepositoryImpl.class,
-
- // common rules
- CommonRuleEngineImpl.class,
- BranchCoverageRule.class,
- LineCoverageRule.class,
- CommentDensityRule.class,
- DuplicatedBlockRule.class,
- TestErrorRule.class,
- SkippedTestRule.class,
-
- // order is important: DebtAggregator then NewDebtAggregator (new debt requires debt)
- DebtCalculator.class,
- DebtAggregator.class,
- NewDebtCalculator.class,
- NewDebtAggregator.class,
- IssueAssigner.class,
- RuleTagsCopier.class,
- IssueCounter.class,
-
- // visitors : order is important, measure computers must be executed at the end in order to access to every measures / issues
- LoadComponentUuidsHavingOpenIssuesVisitor.class,
- IntegrateIssuesVisitor.class,
- CloseIssuesOnRemovedComponentsVisitor.class,
- SqaleMeasuresVisitor.class,
- LastCommitVisitor.class,
- MeasureComputersVisitor.class,
-
- UpdateConflictResolver.class,
- TrackerBaseInputFactory.class,
- TrackerRawInputFactory.class,
- Tracker.class,
- TrackerExecution.class,
- BaseIssuesLoader.class,
-
- // views
- ViewIndex.class,
-
- // ReportProcessor
- ReportProcessor.class);
+ ComputationStepExecutor.class,
+ new ComputationTempFolderProvider(),
+
+ MetricModule.class,
+
+ // holders
+ ReportAnalysisMetadataHolder.class,
+ BatchReportDirectoryHolderImpl.class,
+ ReportTreeRootHolderImpl.class,
+ PeriodsHolderImpl.class,
+ QualityGateHolderImpl.class,
+ DebtModelHolderImpl.class,
+ SqaleRatingSettings.class,
+ ActiveRulesHolderImpl.class,
+ MeasureComputersHolderImpl.class,
+
+ BatchReportReaderImpl.class,
+
+ // repositories
+ LanguageRepositoryImpl.class,
+ MeasureRepositoryImpl.class,
+ EventRepositoryImpl.class,
+ SettingsRepositoryImpl.class,
+ DbIdsRepositoryImpl.class,
+ QualityGateServiceImpl.class,
+ EvaluationResultTextConverterImpl.class,
+
+ // issues
+ RuleCacheLoader.class,
+ RuleRepositoryImpl.class,
+ ScmAccountToUserLoader.class,
+ ScmAccountToUser.class,
+ IssueCache.class,
+ DefaultAssignee.class,
+ IssueVisitors.class,
+ IssueLifecycle.class,
+ ComponentsWithUnprocessedIssues.class,
+ ComponentIssuesRepositoryImpl.class,
+
+ // common rules
+ CommonRuleEngineImpl.class,
+ BranchCoverageRule.class,
+ LineCoverageRule.class,
+ CommentDensityRule.class,
+ DuplicatedBlockRule.class,
+ TestErrorRule.class,
+ SkippedTestRule.class,
+
+ // order is important: DebtAggregator then NewDebtAggregator (new debt requires debt)
+ DebtCalculator.class,
+ DebtAggregator.class,
+ NewDebtCalculator.class,
+ NewDebtAggregator.class,
+ IssueAssigner.class,
+ RuleTagsCopier.class,
+ IssueCounter.class,
+
+ // visitors : order is important, measure computers must be executed at the end in order to access to every measures / issues
+ LoadComponentUuidsHavingOpenIssuesVisitor.class,
+ IntegrateIssuesVisitor.class,
+ CloseIssuesOnRemovedComponentsVisitor.class,
+ SqaleMeasuresVisitor.class,
+ LastCommitVisitor.class,
+ MeasureComputersVisitor.class,
+
+ UpdateConflictResolver.class,
+ TrackerBaseInputFactory.class,
+ TrackerRawInputFactory.class,
+ Tracker.class,
+ TrackerExecution.class,
+ BaseIssuesLoader.class,
+
+ // views
+ ViewIndex.class);
}
-
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/ComputeEngineQueueMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/ComputeEngineQueueMonitor.java
index 7877c677f5b..a5b525d06ac 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/ComputeEngineQueueMonitor.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/monitoring/ComputeEngineQueueMonitor.java
@@ -20,7 +20,7 @@
package org.sonar.server.computation.monitoring;
import java.util.LinkedHashMap;
-import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.CeQueue;
import org.sonar.server.platform.monitoring.BaseMonitorMBean;
public class ComputeEngineQueueMonitor extends BaseMonitorMBean implements ComputeEngineQueueMonitorMBean {
@@ -30,7 +30,7 @@ public class ComputeEngineQueueMonitor extends BaseMonitorMBean implements Compu
// ReportQueue initializes CEQueueStatus and is therefor a dependency of
// ComputeEngineQueueMonitor.
// Do not remove this parameter, it ensures start order of components
- ReportQueue reportQueue) {
+ CeQueue ceQueue) {
this.queueStatus = queueStatus;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolder.java
index eeffd81cd74..07ada89613c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolder.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/MutableQualityGateHolder.java
@@ -19,12 +19,11 @@
*/
package org.sonar.server.computation.qualitygate;
-import org.sonar.server.computation.ReportQueue;
import org.sonar.server.computation.component.Component;
public interface MutableQualityGateHolder extends QualityGateHolder {
/**
- * Sets the quality gate for the project of the currently processed {@link ReportQueue.Item}.
+ * Sets the quality gate.
* Settings a quality gate more than once is not allowed and it can never be set to {@code null}.
*
* @param qualityGate a {@link Component}, can not be {@code null}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolder.java
index 9c75d885d81..ac762d22bee 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolder.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/qualitygate/QualityGateHolder.java
@@ -20,11 +20,10 @@
package org.sonar.server.computation.qualitygate;
import com.google.common.base.Optional;
-import org.sonar.server.computation.ReportQueue;
public interface QualityGateHolder {
/**
- * The QualityGate for the project of the current {@link ReportQueue.Item} if there is any.
+ * The QualityGate for the project if there is any.
*
* @throws IllegalStateException if the holder has not been initialized (ie. we don't know yet what is the QualityGate)
*/
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java
index 232f39392e9..49a06363f60 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateLoadingStep.java
@@ -24,7 +24,6 @@ import org.apache.commons.lang.StringUtils;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.computation.ReportQueue;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.CrawlerDepthLimit;
import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
@@ -38,7 +37,7 @@ import org.sonar.server.computation.qualitygate.QualityGateService;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
/**
- * This step retrieves the QualityGate for the current {@link ReportQueue.Item} and stores it in
+ * This step retrieves the QualityGate and stores it in
* {@link MutableQualityGateHolder}.
*/
public class QualityGateLoadingStep implements ComputationStep {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportExtractionStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportExtractionStep.java
index f3048e9d1fd..77a597116e8 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportExtractionStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportExtractionStep.java
@@ -26,23 +26,26 @@ import org.sonar.api.utils.TempFolder;
import org.sonar.api.utils.ZipUtils;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.utils.log.Profiler;
-import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.ReportFiles;
import org.sonar.server.computation.batch.MutableBatchReportDirectoryHolder;
/**
- * Extracts the content zip file of the {@link ReportQueue.Item} to a temp directory and adds a {@link File}
+ * Extracts the content zip file of the {@link org.sonar.server.computation.CeTask} to a temp directory and adds a {@link File}
* representing that temp directory to the {@link MutableBatchReportDirectoryHolder}.
*/
public class ReportExtractionStep implements ComputationStep {
private static final Logger LOG = Loggers.get(ReportExtractionStep.class);
- private final ReportQueue.Item item;
+ private final ReportFiles reportFiles;
+ private final CeTask task;
private final TempFolder tempFolder;
private final MutableBatchReportDirectoryHolder reportDirectoryHolder;
- public ReportExtractionStep(ReportQueue.Item item, TempFolder tempFolder, MutableBatchReportDirectoryHolder reportDirectoryHolder) {
- this.item = item;
+ public ReportExtractionStep(ReportFiles reportFiles, CeTask task, TempFolder tempFolder,
+ MutableBatchReportDirectoryHolder reportDirectoryHolder) {
+ this.reportFiles = reportFiles;
+ this.task = task;
this.tempFolder = tempFolder;
this.reportDirectoryHolder = reportDirectoryHolder;
}
@@ -50,23 +53,20 @@ public class ReportExtractionStep implements ComputationStep {
@Override
public void execute() {
File dir = tempFolder.newDir();
+ File zip = reportFiles.fileForUuid(task.getUuid());
try {
- Profiler profiler = Profiler.createIfDebug(LOG).start();
- ZipUtils.unzip(item.zipFile, dir);
- if (profiler.isDebugEnabled()) {
- String message = String.format("Report extracted | size=%s | project=%s",
- FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(dir)), item.dto.getProjectKey());
- profiler.stopDebug(message);
- }
+ ZipUtils.unzip(zip, dir);
reportDirectoryHolder.setDirectory(dir);
+ LOG.info("Analysis report extracted | size={} | compressed={}",
+ FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(dir)), FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(zip)));
} catch (IOException e) {
- throw new IllegalStateException(String.format("Fail to unzip %s into %s", item.zipFile, dir), e);
+ throw new IllegalStateException(String.format("Fail to unzip %s into %s", zip, dir), e);
}
}
@Override
public String getDescription() {
- return "Extracting batch report to temp directory";
+ return "Uncompress report";
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeSubmitWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeSubmitWsAction.java
new file mode 100644
index 00000000000..86c25391ce9
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeSubmitWsAction.java
@@ -0,0 +1,93 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.ws;
+
+import java.io.InputStream;
+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.server.computation.CeTask;
+import org.sonar.server.computation.ReportProcessingScheduler;
+import org.sonar.server.computation.ReportSubmitter;
+import org.sonar.server.ws.WsUtils;
+import org.sonarqube.ws.WsCe;
+
+/**
+ * POST api/ce/submit
+ * <p>Submits an analysis report to the queue of Compute Engine</p>
+ */
+public class CeSubmitWsAction implements CeWsAction {
+
+ public static final String PARAM_PROJECT_KEY = "projectKey";
+ public static final String PARAM_PROJECT_NAME = "projectName";
+ public static final String PARAM_REPORT_DATA = "report";
+
+ private final ReportSubmitter reportSubmitter;
+ private final ReportProcessingScheduler reportProcessingScheduler;
+
+ public CeSubmitWsAction(ReportSubmitter reportSubmitter, ReportProcessingScheduler reportProcessingScheduler) {
+ this.reportSubmitter = reportSubmitter;
+ this.reportProcessingScheduler = reportProcessingScheduler;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ WebService.NewAction action = controller.createAction("submit")
+ .setDescription("Submit an analysis report to the queue of Compute Engine. Report is processed asynchronously.")
+ .setPost(true)
+ .setInternal(true)
+ .setHandler(this)
+ .setResponseExample(getClass().getResource("CeSubmitWsAction/example.json"));
+
+ action
+ .createParam(PARAM_PROJECT_KEY)
+ .setRequired(true)
+ .setDescription("Key of project")
+ .setExampleValue("my_project");
+
+ action
+ .createParam(PARAM_PROJECT_NAME)
+ .setRequired(false)
+ .setDescription("Optional name of the project, used only if the project does not exist yet.")
+ .setExampleValue("My Project");
+
+ action
+ .createParam(PARAM_REPORT_DATA)
+ .setRequired(true)
+ .setDescription("Report file. Format is not an API, it changes among SonarQube versions.");
+ }
+
+ @Override
+ public void handle(Request wsRequest, Response wsResponse) throws Exception {
+ String projectKey = wsRequest.mandatoryParam(PARAM_PROJECT_KEY);
+ String projectName = StringUtils.defaultIfBlank(wsRequest.param(PARAM_PROJECT_NAME), projectKey);
+ InputStream reportInput = wsRequest.paramAsInputStream(PARAM_REPORT_DATA);
+
+ CeTask task = reportSubmitter.submit(projectKey, projectName, reportInput);
+ reportProcessingScheduler.startAnalysisTaskNow();
+
+ WsCe.SubmitResponse submitResponse = WsCe.SubmitResponse.newBuilder()
+ .setTaskId(task.getUuid())
+ .setProjectId(task.getComponentUuid())
+ .build();
+ WsUtils.writeProtobuf(submitResponse, wsRequest, wsResponse);
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeTaskWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeTaskWsAction.java
new file mode 100644
index 00000000000..1cd393180ef
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeTaskWsAction.java
@@ -0,0 +1,93 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.ws;
+
+import com.google.common.base.Optional;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.util.Uuids;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.UserSession;
+import org.sonar.server.ws.WsUtils;
+import org.sonarqube.ws.WsCe;
+
+public class CeTaskWsAction implements CeWsAction {
+
+ public static final String ACTION = "task";
+
+ public static final String PARAM_TASK_ID = "id";
+
+ private final DbClient dbClient;
+ private final CeWsTaskFormatter wsTaskFormatter;
+ private final UserSession userSession;
+
+ public CeTaskWsAction(DbClient dbClient, CeWsTaskFormatter wsTaskFormatter, UserSession userSession) {
+ this.dbClient = dbClient;
+ this.wsTaskFormatter = wsTaskFormatter;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ WebService.NewAction action = controller.createAction(ACTION)
+ .setDescription("Task information")
+ .setInternal(true)
+ .setHandler(this);
+
+ action
+ .createParam(PARAM_TASK_ID)
+ .setRequired(true)
+ .setDescription("Id of task")
+ .setExampleValue(Uuids.UUID_EXAMPLE_01);
+ }
+
+ @Override
+ public void handle(Request wsRequest, Response wsResponse) throws Exception {
+ userSession.checkGlobalPermission(UserRole.ADMIN);
+
+ String taskId = wsRequest.mandatoryParam(PARAM_TASK_ID);
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ WsCe.TaskResponse.Builder wsTaskResponse = WsCe.TaskResponse.newBuilder();
+ Optional<CeQueueDto> queueDto = dbClient.ceQueueDao().selectByUuid(dbSession, taskId);
+ if (queueDto.isPresent()) {
+ wsTaskResponse.setTask(wsTaskFormatter.format(queueDto.get()));
+ } else {
+ Optional<CeActivityDto> activityDto = dbClient.ceActivityDao().selectByUuid(dbSession, taskId);
+ if (activityDto.isPresent()) {
+ wsTaskResponse.setTask(wsTaskFormatter.format(activityDto.get()));
+ } else {
+ throw new NotFoundException();
+ }
+ }
+ WsUtils.writeProtobuf(wsTaskResponse.build(), wsRequest, wsResponse);
+
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/ComputationWs.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeWs.java
index 41507396418..45d79d013b0 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/ComputationWs.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeWs.java
@@ -22,20 +22,13 @@ package org.sonar.server.computation.ws;
import org.sonar.api.server.ws.WebService;
-/**
- * Web service to interact with the "computation" stack :
- * <ul>
- * <li>queue of analysis reports to be integrated</li>
- * <li>consolidation and aggregation of analysis measures</li>
- * <li>persistence in datastores (database/elasticsearch)</li>
- * </ul>
- */
-public class ComputationWs implements WebService {
- public static final String ENDPOINT = "api/computation";
+public class CeWs implements WebService {
+
+ public static final String ENDPOINT = "api/ce";
- private final ComputationWsAction[] actions;
+ private final CeWsAction[] actions;
- public ComputationWs(ComputationWsAction... actions) {
+ public CeWs(CeWsAction... actions) {
this.actions = actions;
}
@@ -43,8 +36,8 @@ public class ComputationWs implements WebService {
public void define(Context context) {
NewController controller = context
.createController(ENDPOINT)
- .setDescription("Analysis reports processed");
- for (ComputationWsAction action : actions) {
+ .setDescription("Compute Engine");
+ for (CeWsAction action : actions) {
action.define(controller);
}
controller.done();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/ComputationWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeWsAction.java
index 65edafb7ce4..fb695b052f3 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/ComputationWsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeWsAction.java
@@ -23,10 +23,9 @@ import org.sonar.api.server.ws.WebService;
import org.sonar.server.ws.WsAction;
/**
- * Used by {@link ComputationWs} to
- * loop over all its actions
+ * Used by {@link CeWs} to loop over all its actions
*/
-interface ComputationWsAction extends WsAction {
+interface CeWsAction extends WsAction {
@Override
void define(WebService.NewController controller);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeWsTaskFormatter.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeWsTaskFormatter.java
new file mode 100644
index 00000000000..186175a800d
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/CeWsTaskFormatter.java
@@ -0,0 +1,89 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.ws;
+
+import java.util.Date;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.component.ComponentService;
+import org.sonarqube.ws.WsCe;
+
+public class CeWsTaskFormatter {
+
+ private final ComponentService componentService;
+
+ public CeWsTaskFormatter(ComponentService componentService) {
+ this.componentService = componentService;
+ }
+
+ public WsCe.Task format(CeQueueDto dto) {
+ WsCe.Task.Builder builder = WsCe.Task.newBuilder();
+ builder.setId(dto.getUuid());
+ builder.setStatus(WsCe.TaskStatus.valueOf(dto.getStatus().name()));
+ builder.setTaskType(dto.getTaskType());
+ if (dto.getComponentUuid() != null) {
+ builder.setComponentId(dto.getComponentUuid());
+ buildComponent(builder, dto.getComponentUuid());
+ }
+ if (dto.getSubmitterLogin() != null) {
+ builder.setSubmitterLogin(dto.getSubmitterLogin());
+ }
+ builder.setSubmittedAt(DateUtils.formatDateTime(new Date(dto.getCreatedAt())));
+ if (dto.getStartedAt() != null) {
+ builder.setStartedAt(DateUtils.formatDateTime(new Date(dto.getStartedAt())));
+ }
+ return builder.build();
+ }
+
+ public WsCe.Task format(CeActivityDto dto) {
+ WsCe.Task.Builder builder = WsCe.Task.newBuilder();
+ builder.setId(dto.getUuid());
+ builder.setStatus(WsCe.TaskStatus.valueOf(dto.getStatus().name()));
+ builder.setTaskType(dto.getTaskType());
+ if (dto.getComponentUuid() != null) {
+ builder.setComponentId(dto.getComponentUuid());
+ buildComponent(builder, dto.getComponentUuid());
+ }
+ if (dto.getSubmitterLogin() != null) {
+ builder.setSubmitterLogin(dto.getSubmitterLogin());
+ }
+ builder.setSubmittedAt(DateUtils.formatDateTime(new Date(dto.getCreatedAt())));
+ if (dto.getStartedAt() != null) {
+ builder.setStartedAt(DateUtils.formatDateTime(new Date(dto.getStartedAt())));
+ }
+ if (dto.getFinishedAt() != null) {
+ builder.setFinishedAt(DateUtils.formatDateTime(new Date(dto.getFinishedAt())));
+ }
+ if (dto.getExecutionTimeMs() != null) {
+ builder.setExecutionTimeMs(dto.getExecutionTimeMs());
+ }
+ return builder.build();
+ }
+
+ private void buildComponent(WsCe.Task.Builder builder, String componentUuid) {
+ ComponentDto project = componentService.getNonNullByUuid(componentUuid);
+ if (project != null) {
+ builder.setComponentKey(project.getKey());
+ builder.setComponentName(project.name());
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryAction.java
deleted file mode 100644
index 0320fcdefdf..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/HistoryAction.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.activity.Activity;
-import org.sonar.server.activity.index.ActivityDoc;
-import org.sonar.server.activity.index.ActivityIndex;
-import org.sonar.server.activity.index.ActivityQuery;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.es.SearchResult;
-import org.sonar.server.issue.ws.IssuesWs;
-import org.sonar.server.user.UserSession;
-
-import java.util.Arrays;
-import java.util.Map;
-
-// FIXME replace by api/activities/search
-public class HistoryAction implements ComputationWsAction {
- private final ActivityIndex activityIndex;
- private final UserSession userSession;
-
- public HistoryAction(ActivityIndex activityIndex, UserSession userSession) {
- this.activityIndex = activityIndex;
- this.userSession = userSession;
- }
-
- @Override
- public void define(WebService.NewController controller) {
- WebService.NewAction action = controller
- .createAction("history")
- .setDescription("Past integrations of analysis reports")
- .setSince("5.0")
- .setInternal(true)
- .setHandler(this);
-
- action.addPagingParams(10);
- }
-
- @Override
- public void handle(Request request, Response response) {
- userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
-
- ActivityQuery query = new ActivityQuery();
- query.setTypes(Arrays.asList(Activity.Type.ANALYSIS_REPORT.name()));
-
- SearchOptions options = new SearchOptions();
- options.setPage(request.mandatoryParamAsInt(IssuesWs.Param.PAGE), request.mandatoryParamAsInt(IssuesWs.Param.PAGE_SIZE));
- SearchResult<ActivityDoc> results = activityIndex.search(query, options);
-
- JsonWriter json = response.newJsonWriter().beginObject();
- options.writeJson(json, results.getTotal());
- writeReports(results, json);
- json.endObject().close();
- }
-
- private void writeReports(SearchResult<ActivityDoc> result, JsonWriter json) {
- json.name("reports").beginArray();
- for (ActivityDoc doc : result.getDocs()) {
- json.beginObject();
- for (Map.Entry<String, String> detail : doc.getDetails().entrySet()) {
- json.prop(detail.getKey(), detail.getValue());
- }
- json.endObject();
- }
- json.endArray();
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/IsQueueEmptyWs.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/IsQueueEmptyWs.java
index fb247eac52d..a789d61c94a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/IsQueueEmptyWs.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/IsQueueEmptyWs.java
@@ -25,10 +25,8 @@ import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.RequestHandler;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.server.computation.ReportQueue;
-
-import java.util.List;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
/**
* Internal WebService with one action
@@ -38,8 +36,8 @@ public class IsQueueEmptyWs implements WebService {
private final IsQueueEmptyAction action;
- public IsQueueEmptyWs(ReportQueue queue) {
- this.action = new IsQueueEmptyAction(queue);
+ public IsQueueEmptyWs(DbClient dbClient) {
+ this.action = new IsQueueEmptyAction(dbClient);
}
@Override
@@ -52,26 +50,29 @@ public class IsQueueEmptyWs implements WebService {
}
static class IsQueueEmptyAction implements RequestHandler {
- private final ReportQueue queue;
+ private final DbClient dbClient;
- public IsQueueEmptyAction(ReportQueue queue) {
- this.queue = queue;
+ public IsQueueEmptyAction(DbClient dbClient) {
+ this.dbClient = dbClient;
}
public void define(WebService.NewController controller) {
controller
.createAction("is_queue_empty")
- .setDescription("Check if the analysis report queue is empty")
+ .setDescription("Check if the queue of Compute Engine is empty")
.setInternal(true)
.setHandler(this);
}
@Override
public void handle(Request request, Response response) throws Exception {
- List<AnalysisReportDto> reports = queue.all();
- boolean isQueueEmpty = reports.isEmpty();
-
- IOUtils.write(String.valueOf(isQueueEmpty), response.stream().output());
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ boolean isQueueEmpty = dbClient.ceQueueDao().selectAllInAscOrder(dbSession).isEmpty();
+ IOUtils.write(String.valueOf(isQueueEmpty), response.stream().output());
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
}
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueAction.java
deleted file mode 100644
index 1ea1a4845d6..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/QueueAction.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.server.computation.ReportQueue;
-
-import java.util.List;
-
-import static org.sonar.api.utils.DateUtils.longToDate;
-
-/**
- * @since 5.0
- */
-public class QueueAction implements ComputationWsAction {
- private final ReportQueue queue;
-
- public QueueAction(ReportQueue queue) {
- this.queue = queue;
- }
-
- @Override
- public void define(WebService.NewController controller) {
- controller
- .createAction("queue")
- .setDescription("List all the active analysis reports")
- .setSince("5.0")
- .setInternal(true)
- .setHandler(this);
- }
-
- @Override
- public void handle(Request request, Response response) throws Exception {
- List<AnalysisReportDto> reports = queue.all();
-
- JsonWriter json = response.newJsonWriter().beginObject();
- writeReports(reports, json);
- json.endObject();
- json.close();
- }
-
- private static void writeReports(List<AnalysisReportDto> reports, JsonWriter json) {
- json.name("reports").beginArray();
- for (AnalysisReportDto report : reports) {
- json.beginObject();
- json.prop("key", report.getId());
- json.prop("projectKey", report.getProjectKey());
- json.prop("projectName", report.getProjectName());
- json.propDateTime("startedAt", longToDate(report.getStartedAt()));
- json.propDateTime("finishedAt", longToDate(report.getFinishedAt()));
- json.propDateTime("submittedAt", longToDate(report.getCreatedAt()));
- json.prop("status", report.getStatus().toString());
- json.endObject();
- }
- json.endArray();
- }
-
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportAction.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportAction.java
deleted file mode 100644
index a908efa46fe..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ws/SubmitReportAction.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import java.io.InputStream;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.computation.ReportProcessingScheduler;
-import org.sonar.server.computation.ReportQueue;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
-import org.sonar.server.user.UserSession;
-
-public class SubmitReportAction implements ComputationWsAction {
-
- public static final String ACTION = "submit_report";
- public static final String PARAM_PROJECT_KEY = "projectKey";
- public static final String PARAM_PROJECT_NAME = "projectName";
- public static final String PARAM_REPORT_DATA = "report";
-
- private final ReportQueue queue;
- private final ReportProcessingScheduler workerLauncher;
- private final UserSession userSession;
- private final CEQueueStatus queueStatus;
-
- public SubmitReportAction(ReportQueue queue, ReportProcessingScheduler workerLauncher, UserSession userSession, CEQueueStatus queueStatus) {
- this.queue = queue;
- this.workerLauncher = workerLauncher;
- this.userSession = userSession;
- this.queueStatus = queueStatus;
- }
-
- @Override
- public void define(WebService.NewController controller) {
- WebService.NewAction action = controller.createAction(ACTION)
- .setDescription("Submit an analysis report to the queue. Report is integrated asynchronously.")
- .setPost(true)
- .setInternal(true)
- .setHandler(this);
-
- action
- .createParam(PARAM_PROJECT_KEY)
- .setRequired(true)
- .setDescription("Project key")
- .setExampleValue("org.codehaus.sonar:sonar");
-
- action
- .createParam(PARAM_PROJECT_NAME)
- .setRequired(true)
- .setDescription("Project name")
- .setExampleValue("SonarQube");
-
- action
- .createParam(PARAM_REPORT_DATA)
- .setRequired(true)
- .setDescription("Report file. Format is not an API, it changes among SonarQube versions.");
- }
-
- @Override
- public void handle(Request request, Response response) throws Exception {
- userSession.checkGlobalPermission(GlobalPermissions.SCAN_EXECUTION);
- String projectKey = request.mandatoryParam(PARAM_PROJECT_KEY);
- String projectName = request.mandatoryParam(PARAM_PROJECT_NAME);
- InputStream reportData = request.paramAsInputStream(PARAM_REPORT_DATA);
- try {
- ReportQueue.Item item = queue.add(projectKey, projectName, reportData);
- queueStatus.addReceived();
- workerLauncher.startAnalysisTaskNow();
- response.newJsonWriter()
- .beginObject()
- // do not write integer for forward-compatibility, for example
- // if we want to write UUID later
- .prop("key", String.valueOf(item.dto.getId()))
- .endObject()
- .close();
- } finally {
- IOUtils.closeQuietly(reportData);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
index 5a1c1e91476..9f21e781cd2 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
@@ -64,14 +64,19 @@ import org.sonar.server.component.DefaultRubyComponentService;
import org.sonar.server.component.ws.ComponentsWs;
import org.sonar.server.component.ws.EventsWs;
import org.sonar.server.component.ws.ResourcesWs;
+import org.sonar.server.computation.CeQueue;
+import org.sonar.server.computation.CeQueueInitializer;
+import org.sonar.server.computation.CleanReportQueueListener;
import org.sonar.server.computation.ComputeEngineProcessingModule;
-import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.ReportFiles;
+import org.sonar.server.computation.ReportSubmitter;
import org.sonar.server.computation.monitoring.CEQueueStatusImpl;
import org.sonar.server.computation.monitoring.ComputeEngineQueueMonitor;
-import org.sonar.server.computation.ws.ComputationWs;
-import org.sonar.server.computation.ws.HistoryAction;
+import org.sonar.server.computation.ws.CeSubmitWsAction;
+import org.sonar.server.computation.ws.CeTaskWsAction;
+import org.sonar.server.computation.ws.CeWs;
+import org.sonar.server.computation.ws.CeWsTaskFormatter;
import org.sonar.server.computation.ws.IsQueueEmptyWs;
-import org.sonar.server.computation.ws.QueueAction;
import org.sonar.server.config.ws.PropertiesWs;
import org.sonar.server.dashboard.template.GlobalDefaultDashboard;
import org.sonar.server.dashboard.template.ProjectDefaultDashboard;
@@ -711,17 +716,21 @@ public class PlatformLevel4 extends PlatformLevel {
// Compute engine
CEQueueStatusImpl.class,
ComputeEngineQueueMonitor.class,
- ReportQueue.class,
+ CeQueue.class,
+ CleanReportQueueListener.class,
+ ReportFiles.class,
ComputeEngineProcessingModule.class,
- ComputationWs.class,
+ CeWs.class,
+ CeWsTaskFormatter.class,
+ CeTaskWsAction.class,
+ CeSubmitWsAction.class,
IsQueueEmptyWs.class,
- QueueAction.class,
- HistoryAction.class,
DefaultPeriodCleaner.class,
ProjectCleaner.class,
ProjectSettingsFactory.class,
IndexPurgeListener.class,
-
+ ReportSubmitter.class,
+ CeQueueInitializer.class,
// Views plugin
ViewsBootstrap.class,
ViewsStopper.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java
index 80141a36266..f463289c455 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java
@@ -19,7 +19,7 @@
*/
package org.sonar.server.platform.platformlevel;
-import org.sonar.server.computation.ReportQueueCleaner;
+import org.sonar.server.computation.CeQueueInitializer;
import org.sonar.server.issue.filter.RegisterIssueFilters;
import org.sonar.server.platform.ServerLifecycleNotifier;
import org.sonar.server.qualitygate.RegisterQualityGates;
@@ -62,7 +62,6 @@ public class PlatformLevelStartup extends PlatformLevel {
RenameDeprecatedPropertyKeys.class,
LogServerId.class,
RegisterServletFilters.class,
- ReportQueueCleaner.class,
RegisterIssueFilters.class,
RenameIssueWidgets.class,
ServerLifecycleNotifier.class);
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/computation/ws/CeSubmitWsAction/example.json b/server/sonar-server/src/main/resources/org/sonar/server/computation/ws/CeSubmitWsAction/example.json
new file mode 100644
index 00000000000..7cee04f5da8
--- /dev/null
+++ b/server/sonar-server/src/main/resources/org/sonar/server/computation/ws/CeSubmitWsAction/example.json
@@ -0,0 +1,4 @@
+{
+ "taskId": "TASK_1",
+ "projectId": "PROJECT_1"
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsModuleTest.java
index 009d79afd9a..997ac69ffec 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsModuleTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsModuleTest.java
@@ -29,7 +29,7 @@ public class BatchWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new BatchWsModule().configure(container);
- assertThat(container.size()).isEqualTo(10);
+ assertThat(container.size()).isEqualTo(9);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceTest.java
index f98d960959e..437bc00738f 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceTest.java
@@ -270,7 +270,7 @@ public class ComponentServiceTest {
public void create_project() {
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.PROVISIONING);
- String key = service.create(NewComponent.create("struts", "Struts project"));
+ String key = service.create(NewComponent.create("struts", "Struts project")).getKey();
ComponentDto project = service.getNullableByKey(key);
assertThat(project.key()).isEqualTo("struts");
@@ -290,7 +290,7 @@ public class ComponentServiceTest {
public void create_new_project_with_branch() {
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.PROVISIONING);
- String key = service.create(NewComponent.create("struts", "Struts project").setBranch("origin/branch"));
+ String key = service.create(NewComponent.create("struts", "Struts project").setBranch("origin/branch")).getKey();
ComponentDto project = service.getNullableByKey(key);
assertThat(project.key()).isEqualTo("struts:origin/branch");
@@ -301,7 +301,7 @@ public class ComponentServiceTest {
public void create_view() {
userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.PROVISIONING);
- String key = service.create(NewComponent.create("all-project", "All Projects").setQualifier(Qualifiers.VIEW));
+ String key = service.create(NewComponent.create("all-project", "All Projects").setQualifier(Qualifiers.VIEW)).getKey();
ComponentDto project = service.getNullableByKey(key);
assertThat(project.key()).isEqualTo("all-project");
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java
index b4d15d288df..08ca3c7ecbb 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java
@@ -87,8 +87,9 @@ public class DefaultRubyComponentServiceTest {
String componentKey = "new-project";
String componentName = "New Project";
String qualifier = Qualifiers.PROJECT;
- when(resourceDao.selectByKey(componentKey)).thenReturn(ComponentTesting.newProjectDto());
- when(componentService.create(any(NewComponent.class))).thenReturn(componentKey);
+ ComponentDto projectDto = ComponentTesting.newProjectDto().setKey(componentKey);
+ when(resourceDao.selectByKey(componentKey)).thenReturn(projectDto);
+ when(componentService.create(any(NewComponent.class))).thenReturn(projectDto);
service.createComponent(componentKey, componentName, qualifier);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/CeQueueInitializerTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/CeQueueInitializerTest.java
new file mode 100644
index 00000000000..11b41917b1b
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/CeQueueInitializerTest.java
@@ -0,0 +1,139 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
+import org.sonar.api.platform.ServerUpgradeStatus;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.server.computation.monitoring.CEQueueStatus;
+import org.sonar.server.computation.monitoring.CEQueueStatusImpl;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class CeQueueInitializerTest {
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ @Rule
+ public TemporaryFolder tempFolder = new TemporaryFolder();
+
+ ServerUpgradeStatus serverUpgradeStatus = mock(ServerUpgradeStatus.class);
+ ReportFiles reportFiles = mock(ReportFiles.class, Mockito.RETURNS_DEEP_STUBS);
+ CeQueue queue = mock(CeQueue.class);
+ CEQueueStatus queueStatus = new CEQueueStatusImpl();
+ CeQueueInitializer underTest = new CeQueueInitializer(dbTester.getDbClient(), serverUpgradeStatus, reportFiles, queue, queueStatus);
+
+ @Test
+ public void init_jmx_counters() throws IOException {
+ insertInQueue("TASK_1", CeQueueDto.Status.PENDING);
+ insertInQueue("TASK_2", CeQueueDto.Status.PENDING);
+ // this in-progress task is going to be moved to PENDING
+ insertInQueue("TASK_3", CeQueueDto.Status.IN_PROGRESS);
+
+ underTest.start();
+
+ assertThat(queueStatus.getPendingCount()).isEqualTo(3);
+ }
+
+ @Test
+ public void init_jmx_counters_when_queue_is_empty() {
+ underTest.start();
+
+ assertThat(queueStatus.getPendingCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void reset_in_progress_tasks_to_pending() throws IOException {
+ insertInQueue("TASK_1", CeQueueDto.Status.PENDING);
+ insertInQueue("TASK_2", CeQueueDto.Status.IN_PROGRESS);
+
+ underTest.start();
+
+ assertThat(dbTester.getDbClient().ceQueueDao().countByStatus(dbTester.getSession(), CeQueueDto.Status.PENDING)).isEqualTo(2);
+ assertThat(dbTester.getDbClient().ceQueueDao().countByStatus(dbTester.getSession(), CeQueueDto.Status.IN_PROGRESS)).isEqualTo(0);
+ }
+
+ @Test
+ public void clear_queue_if_version_upgrade() {
+ when(serverUpgradeStatus.isUpgraded()).thenReturn(true);
+
+ underTest.start();
+
+ verify(queue).clear();
+ }
+
+ @Test
+ public void cancel_task_if_report_file_is_missing() throws IOException {
+ CeQueueDto task = insertInQueue("TASK_1", CeQueueDto.Status.PENDING, false);
+
+ underTest.start();
+
+ verify(queue).cancel(any(DbSession.class), eq(task));
+ }
+
+ @Test
+ public void delete_orphan_report_files() throws Exception {
+ // two files on disk but on task in queue
+ insertInQueue("TASK_1", CeQueueDto.Status.PENDING, true);
+ when(reportFiles.listUuids()).thenReturn(asList("TASK_1", "TASK_2"));
+
+ underTest.start();
+
+ verify(reportFiles).deleteIfExists("TASK_2");
+ }
+
+ private void insertInQueue(String taskUuid, CeQueueDto.Status status) throws IOException {
+ insertInQueue(taskUuid, status, true);
+ }
+
+ private CeQueueDto insertInQueue(String taskUuid, CeQueueDto.Status status, boolean createFile) throws IOException {
+ CeQueueDto queueDto = new CeQueueDto();
+ queueDto.setTaskType(CeTaskTypes.REPORT);
+ queueDto.setComponentUuid("PROJECT_1");
+ queueDto.setUuid(taskUuid);
+ queueDto.setStatus(status);
+ dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
+ dbTester.getSession().commit();
+
+ File file = tempFolder.newFile();
+ when(reportFiles.fileForUuid(taskUuid)).thenReturn(file);
+ if (!createFile) {
+ file.delete();
+ }
+ return queueDto;
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/CeQueueTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/CeQueueTest.java
new file mode 100644
index 00000000000..0f0939c2ea3
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/CeQueueTest.java
@@ -0,0 +1,219 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import com.google.common.base.Optional;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.core.util.UuidFactoryImpl;
+import org.sonar.db.DbTester;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.server.computation.monitoring.CEQueueStatus;
+import org.sonar.server.computation.monitoring.CEQueueStatusImpl;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.startsWith;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+public class CeQueueTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ System2 system2 = new TestSystem2().setNow(1_450_000_000_000L);
+
+ @Rule
+ public DbTester dbTester = DbTester.create(system2);
+
+ UuidFactory uuidFactory = UuidFactoryImpl.INSTANCE;
+ CEQueueStatus queueStatus = new CEQueueStatusImpl();
+ CeQueueListener listener = mock(CeQueueListener.class);
+ CeQueue underTest = new CeQueue(system2, dbTester.getDbClient(), uuidFactory, queueStatus, new CeQueueListener[] {listener});
+
+ @Test
+ public void test_submit() {
+ CeTaskSubmit submit = underTest.prepareSubmit();
+ submit.setComponentUuid("PROJECT_1");
+ submit.setType(CeTaskTypes.REPORT);
+ submit.setSubmitterLogin("rob");
+
+ CeTask task = underTest.submit(submit);
+ assertThat(task.getUuid()).isEqualTo(submit.getUuid());
+ assertThat(task.getComponentUuid()).isEqualTo("PROJECT_1");
+ assertThat(task.getSubmitterLogin()).isEqualTo("rob");
+
+ Optional<CeQueueDto> queueDto = dbTester.getDbClient().ceQueueDao().selectByUuid(dbTester.getSession(), submit.getUuid());
+ assertThat(queueDto.isPresent()).isTrue();
+ assertThat(queueDto.get().getTaskType()).isEqualTo(CeTaskTypes.REPORT);
+ assertThat(queueDto.get().getComponentUuid()).isEqualTo("PROJECT_1");
+ assertThat(queueDto.get().getSubmitterLogin()).isEqualTo("rob");
+ assertThat(queueDto.get().getCreatedAt()).isEqualTo(1_450_000_000_000L);
+ assertThat(queueStatus.getReceivedCount()).isEqualTo(1L);
+ }
+
+ @Test
+ public void fail_to_submit_if_paused() {
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Compute Engine does not currently accept new tasks");
+ underTest.pauseSubmit();
+
+ submit(CeTaskTypes.REPORT, "PROJECT_1");
+ }
+
+ @Test
+ public void test_remove() {
+ CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
+ Optional<CeTask> peek = underTest.peek();
+ underTest.remove(peek.get(), CeActivityDto.Status.SUCCESS);
+
+ // queue is empty
+ assertThat(dbTester.getDbClient().ceQueueDao().selectByUuid(dbTester.getSession(), task.getUuid()).isPresent()).isFalse();
+ assertThat(underTest.peek().isPresent()).isFalse();
+
+ // available in history
+ Optional<CeActivityDto> history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), task.getUuid());
+ assertThat(history.isPresent()).isTrue();
+ assertThat(history.get().getStatus()).isEqualTo(CeActivityDto.Status.SUCCESS);
+ assertThat(history.get().getIsLast()).isTrue();
+
+ verify(listener).onRemoved(task, CeActivityDto.Status.SUCCESS);
+ }
+
+ @Test
+ public void fail_to_remove_if_not_in_queue() throws Exception {
+ expectedException.expect(IllegalStateException.class);
+ CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
+ underTest.remove(task, CeActivityDto.Status.SUCCESS);
+
+ // fail
+ underTest.remove(task, CeActivityDto.Status.SUCCESS);
+ }
+
+ @Test
+ public void test_peek() throws Exception {
+ CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
+
+ Optional<CeTask> peek = underTest.peek();
+ assertThat(peek.isPresent()).isTrue();
+ assertThat(peek.get().getUuid()).isEqualTo(task.getUuid());
+ assertThat(peek.get().getType()).isEqualTo(CeTaskTypes.REPORT);
+ assertThat(peek.get().getComponentUuid()).isEqualTo("PROJECT_1");
+
+ // no more pending tasks
+ peek = underTest.peek();
+ assertThat(peek.isPresent()).isFalse();
+
+ verify(listener, never()).onRemoved(eq(task), any(CeActivityDto.Status.class));
+ }
+
+ @Test
+ public void peek_nothing_if_paused() throws Exception {
+ submit(CeTaskTypes.REPORT, "PROJECT_1");
+ underTest.pausePeek();
+
+ Optional<CeTask> peek = underTest.peek();
+ assertThat(peek.isPresent()).isFalse();
+ }
+
+ @Test
+ public void cancel_pending() throws Exception {
+ CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
+
+ // ignore
+ boolean canceled = underTest.cancel("UNKNOWN");
+ assertThat(canceled).isFalse();
+ verifyZeroInteractions(listener);
+
+ canceled = underTest.cancel(task.getUuid());
+ assertThat(canceled).isTrue();
+ Optional<CeActivityDto> activity = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), task.getUuid());
+ assertThat(activity.isPresent()).isTrue();
+ assertThat(activity.get().getStatus()).isEqualTo(CeActivityDto.Status.CANCELED);
+ verify(listener).onRemoved(task, CeActivityDto.Status.CANCELED);
+ }
+
+ @Test
+ public void fail_to_cancel_if_in_progress() throws Exception {
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage(startsWith("Task is in progress and can't be cancelled"));
+
+ CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
+ underTest.peek();
+
+ underTest.cancel(task.getUuid());
+ }
+
+ @Test
+ public void cancelAll_pendings_but_not_in_progress() throws Exception {
+ CeTask inProgressTask = submit(CeTaskTypes.REPORT, "PROJECT_1");
+ CeTask pendingTask1 = submit(CeTaskTypes.REPORT, "PROJECT_2");
+ CeTask pendingTask2 = submit(CeTaskTypes.REPORT, "PROJECT_3");
+ underTest.peek();
+
+ int canceledCount = underTest.cancelAll();
+ assertThat(canceledCount).isEqualTo(2);
+
+ Optional<CeActivityDto> history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), pendingTask1.getUuid());
+ assertThat(history.get().getStatus()).isEqualTo(CeActivityDto.Status.CANCELED);
+ history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), pendingTask2.getUuid());
+ assertThat(history.get().getStatus()).isEqualTo(CeActivityDto.Status.CANCELED);
+ history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), inProgressTask.getUuid());
+ assertThat(history.isPresent()).isFalse();
+
+ verify(listener).onRemoved(pendingTask1, CeActivityDto.Status.CANCELED);
+ verify(listener).onRemoved(pendingTask2, CeActivityDto.Status.CANCELED);
+ }
+
+ @Test
+ public void pause_and_resume_submits() throws Exception {
+ assertThat(underTest.isSubmitPaused()).isFalse();
+ underTest.pauseSubmit();
+ assertThat(underTest.isSubmitPaused()).isTrue();
+ underTest.resumeSubmit();
+ assertThat(underTest.isSubmitPaused()).isFalse();
+ }
+
+ @Test
+ public void pause_and_resume_peeks() throws Exception {
+ assertThat(underTest.isPeekPaused()).isFalse();
+ underTest.pausePeek();
+ assertThat(underTest.isPeekPaused()).isTrue();
+ underTest.resumePeek();
+ assertThat(underTest.isPeekPaused()).isFalse();
+ }
+
+ private CeTask submit(String reportType, String componentUuid) {
+ CeTaskSubmit submit = underTest.prepareSubmit();
+ submit.setType(reportType);
+ submit.setComponentUuid(componentUuid);
+ return underTest.submit(submit);
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/CeWorkerImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/CeWorkerImplTest.java
new file mode 100644
index 00000000000..aed8a4a450a
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/CeWorkerImplTest.java
@@ -0,0 +1,72 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import com.google.common.base.Optional;
+import org.junit.Test;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.db.ce.CeTaskTypes;
+
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+public class CeWorkerImplTest {
+
+ CeQueue queue = mock(CeQueue.class);
+ ReportTaskProcessor taskProcessor = mock(ReportTaskProcessor.class);
+ CeWorker underTest = new CeWorkerImpl(queue, taskProcessor);
+
+ @Test
+ public void no_pending_tasks_in_queue() throws Exception {
+ when(queue.peek()).thenReturn(Optional.<CeTask>absent());
+
+ underTest.run();
+
+ verifyZeroInteractions(taskProcessor);
+ }
+
+ @Test
+ public void peek_and_process_task() throws Exception {
+ CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", null);
+ when(queue.peek()).thenReturn(Optional.of(task));
+
+ underTest.run();
+
+ verify(taskProcessor).process(task);
+ verify(queue).remove(task, CeActivityDto.Status.SUCCESS);
+ }
+
+ @Test
+ public void fail_to_process_task() throws Exception {
+ CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", null);
+ when(queue.peek()).thenReturn(Optional.of(task));
+ doThrow(new IllegalStateException()).when(taskProcessor).process(task);
+
+ underTest.run();
+
+ verify(taskProcessor).process(task);
+ verify(queue).remove(task, CeActivityDto.Status.FAILED);
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/CleanReportQueueListenerTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/CleanReportQueueListenerTest.java
new file mode 100644
index 00000000000..0d6a631ba63
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/CleanReportQueueListenerTest.java
@@ -0,0 +1,49 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import org.junit.Test;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.db.ce.CeTaskTypes;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class CleanReportQueueListenerTest {
+
+ ReportFiles reportFiles = mock(ReportFiles.class);
+ CleanReportQueueListener underTest = new CleanReportQueueListener(reportFiles);
+
+ @Test
+ public void remove_report_file_if_success() {
+ CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", null);
+
+ underTest.onRemoved(task, CeActivityDto.Status.SUCCESS);
+ verify(reportFiles).deleteIfExists("TASK_1");
+ }
+
+ @Test
+ public void remove_report_file_if_failure() {
+ CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", null);
+
+ underTest.onRemoved(task, CeActivityDto.Status.FAILED);
+ verify(reportFiles).deleteIfExists("TASK_1");
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputeEngineProcessingQueueImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputeEngineProcessingQueueImplTest.java
index a45fadec0fc..3d29d79ac1e 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputeEngineProcessingQueueImplTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputeEngineProcessingQueueImplTest.java
@@ -54,7 +54,7 @@ public class ComputeEngineProcessingQueueImplTest {
@Test
public void task_in_queue_is_called_run_only_once() {
ComputeEngineProcessingExecutorServiceAdapter processingExecutorService = new SimulateFixedRateCallsProcessingExecutorService(10);
- CallCounterComputeEngineTask task = new CallCounterComputeEngineTask();
+ CallCounterCeWorker task = new CallCounterCeWorker();
ComputeEngineProcessingQueueImpl underTest = new ComputeEngineProcessingQueueImpl(processingExecutorService);
underTest.addTask(task);
@@ -70,25 +70,25 @@ public class ComputeEngineProcessingQueueImplTest {
final List<Integer> nameList = new ArrayList<>();
ComputeEngineProcessingQueueImpl underTest = new ComputeEngineProcessingQueueImpl(processingExecutorService);
- underTest.addTask(new ComputeEngineTask() {
+ underTest.addTask(new CeWorker() {
@Override
public void run() {
nameList.add(1);
}
});
- underTest.addTask(new ComputeEngineTask() {
+ underTest.addTask(new CeWorker() {
@Override
public void run() {
nameList.add(2);
}
});
- underTest.addTask(new ComputeEngineTask() {
+ underTest.addTask(new CeWorker() {
@Override
public void run() {
nameList.add(3);
}
});
- underTest.addTask(new ComputeEngineTask() {
+ underTest.addTask(new CeWorker() {
@Override
public void run() {
nameList.add(4);
@@ -105,7 +105,7 @@ public class ComputeEngineProcessingQueueImplTest {
ComputeEngineProcessingExecutorServiceAdapter processingExecutorService = new SimulateFixedRateCallsProcessingExecutorService(1);
ComputeEngineProcessingQueueImpl underTest = new ComputeEngineProcessingQueueImpl(processingExecutorService);
- underTest.addTask(new ComputeEngineTask() {
+ underTest.addTask(new CeWorker() {
@Override
public void run() {
throw new RuntimeException("This should be caught by the processing queue");
@@ -115,7 +115,7 @@ public class ComputeEngineProcessingQueueImplTest {
underTest.onServerStart(mock(Server.class));
}
- private static class CallCounterComputeEngineTask implements ComputeEngineTask {
+ private static class CallCounterCeWorker implements CeWorker {
int calls = 0;
@Override
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessingSchedulerTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessingSchedulerTest.java
index 5a4e36e3f2d..51cc29f5469 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessingSchedulerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessingSchedulerTest.java
@@ -27,7 +27,6 @@ import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.sonar.api.platform.Server;
-import org.sonar.core.platform.ComponentContainer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
@@ -38,66 +37,41 @@ import static org.mockito.Mockito.when;
public class ReportProcessingSchedulerTest {
- private ReportProcessingSchedulerExecutorService batchExecutorService = mock(ReportProcessingSchedulerExecutorService.class);
- private SimpleComputeEngineProcessingQueue processingQueue = new SimpleComputeEngineProcessingQueue();
- private ReportQueue queue = mock(ReportQueue.class);
- private ComponentContainer componentContainer = mock(ComponentContainer.class);
-
- private ReportProcessingScheduler underTest = new ReportProcessingScheduler(batchExecutorService, processingQueue, queue, componentContainer);
+ ReportProcessingSchedulerExecutorService batchExecutorService = mock(ReportProcessingSchedulerExecutorService.class);
+ SimpleComputeEngineProcessingQueue processingQueue = new SimpleComputeEngineProcessingQueue();
+ CeWorker worker = mock(CeWorker.class);
+ ReportProcessingScheduler underTest = new ReportProcessingScheduler(batchExecutorService, processingQueue, worker);
@Test
- public void schedule_at_fixed_rate_adding_a_ReportProcessingTask_to_the_queue_if_there_is_item_in_ReportQueue() {
- ReportQueue.Item item = mock(ReportQueue.Item.class);
+ public void schedule_at_fixed_rate_adding_a_ReportProcessingTask_to_the_queue() throws Exception {
when(batchExecutorService.scheduleAtFixedRate(any(Runnable.class), eq(0L), eq(10L), eq(TimeUnit.SECONDS)))
.thenAnswer(new ExecuteFirstArgAsRunnable());
- when(queue.pop()).thenReturn(item);
underTest.onServerStart(mock(Server.class));
assertThat(processingQueue.getTasks()).hasSize(1);
- assertThat(processingQueue.getTasks().iterator().next()).isInstanceOf(ReportProcessingTask.class);
- }
-
- @Test
- public void schedule_at_fixed_rate_does_not_add_ReportProcessingTask_to_the_queue_if_there_is_no_item_in_ReportQueue() {
- when(batchExecutorService.scheduleAtFixedRate(any(Runnable.class), eq(0L), eq(10L), eq(TimeUnit.SECONDS)))
- .thenAnswer(new ExecuteFirstArgAsRunnable());
-
- underTest.onServerStart(mock(Server.class));
-
- assertThat(processingQueue.getTasks()).isEmpty();
+ assertThat(processingQueue.getTasks().iterator().next()).isInstanceOf(CeWorker.class);
}
@Test
- public void adds_immediately_a_ReportProcessingTask_to_the_queue_if_there_is_item_in_ReportQueue() {
- ReportQueue.Item item = mock(ReportQueue.Item.class);
+ public void adds_immediately_a_ReportProcessingTask_to_the_queue() throws Exception {
doAnswer(new ExecuteFirstArgAsRunnable()).when(batchExecutorService).execute(any(Runnable.class));
- when(queue.pop()).thenReturn(item);
underTest.startAnalysisTaskNow();
assertThat(processingQueue.getTasks()).hasSize(1);
- assertThat(processingQueue.getTasks().iterator().next()).isInstanceOf(ReportProcessingTask.class);
- }
-
- @Test
- public void adds_immediately_does_not_add_ReportProcessingTask_to_the_queue_if_there_is_item_in_ReportQueue() {
- doAnswer(new ExecuteFirstArgAsRunnable()).when(batchExecutorService).execute(any(Runnable.class));
-
- underTest.startAnalysisTaskNow();
-
- assertThat(processingQueue.getTasks()).isEmpty();
+ assertThat(processingQueue.getTasks().iterator().next()).isInstanceOf(CeWorker.class);
}
private static class SimpleComputeEngineProcessingQueue implements ComputeEngineProcessingQueue {
- private final List<ComputeEngineTask> tasks = new ArrayList<>();
+ private final List<CeWorker> tasks = new ArrayList<>();
@Override
- public void addTask(ComputeEngineTask task) {
+ public void addTask(CeWorker task) {
tasks.add(task);
}
- public List<ComputeEngineTask> getTasks() {
+ public List<CeWorker> getTasks() {
return tasks;
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessingTaskTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessingTaskTest.java
deleted file mode 100644
index 7b8b399f837..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessingTaskTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation;
-
-import java.io.File;
-import java.io.IOException;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.core.platform.ComponentContainer;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.server.computation.container.ComputeEngineContainer;
-import org.sonar.server.computation.container.ContainerFactory;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class ReportProcessingTaskTest {
-
- private static final long ANALYSIS_REPORT_DTO_ID = 663l;
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
- @Rule
- public LogTester logTester = new LogTester();
-
- ReportQueue queue = mock(ReportQueue.class);
- ComponentContainer componentContainer = mock(ComponentContainer.class);
- ContainerFactory containerFactory = mock(ContainerFactory.class);
- ReportQueue.Item item = new ReportQueue.Item(createAnalysisReportDto(), new File("Don't care"));
-
- private static AnalysisReportDto createAnalysisReportDto() {
- AnalysisReportDto res = new AnalysisReportDto();
- res.setProjectKey("P1").setId(ANALYSIS_REPORT_DTO_ID);
- return res;
- }
-
- ReportProcessingTask underTest = new ReportProcessingTask(queue, item, componentContainer, containerFactory);
-
- @Test
- public void creates_container_for_item_run_its_ReportProcessor_and_remove_from_queue() throws IOException {
- ComputeEngineContainer computeEngineContainer = mock(ComputeEngineContainer.class);
- when(containerFactory.create(componentContainer, item)).thenReturn(computeEngineContainer);
-
- ReportProcessor reportProcessor = mock(ReportProcessor.class);
- when(computeEngineContainer.getComponentByType(ReportProcessor.class)).thenReturn(reportProcessor);
-
- underTest.run();
-
- verify(containerFactory).create(componentContainer, item);
- verify(reportProcessor).process();
- verify(computeEngineContainer).cleanup();
- verify(queue).remove(item);
- }
-
- @Test
- public void remove_from_queue_even_if_process_failed() throws IOException {
- ComputeEngineContainer computeEngineContainer = mock(ComputeEngineContainer.class);
- when(containerFactory.create(componentContainer, item)).thenReturn(computeEngineContainer);
-
- ReportProcessor reportProcessor = mock(ReportProcessor.class);
- when(computeEngineContainer.getComponentByType(ReportProcessor.class)).thenReturn(reportProcessor);
- doThrow(new IllegalArgumentException("This exception must be silently logged by ReportProcessingTask"))
- .when(reportProcessor)
- .process();
-
- underTest.run();
-
- verify(containerFactory).create(componentContainer, item);
- verify(reportProcessor).process();
- verify(computeEngineContainer).cleanup();
- verify(queue).remove(item);
- }
-
- @Test
- public void handle_error_during_removal_from_queue() throws Exception {
- ComputeEngineContainer computeEngineContainer = mock(ComputeEngineContainer.class);
- when(containerFactory.create(componentContainer, item)).thenReturn(computeEngineContainer);
-
- ReportProcessor reportProcessor = mock(ReportProcessor.class);
- when(computeEngineContainer.getComponentByType(ReportProcessor.class)).thenReturn(reportProcessor);
-
- doThrow(new IllegalStateException("pb")).when(queue).remove(item);
-
- underTest.run();
-
- assertThat(logTester.logs()).contains("Failed to remove analysis report " + ANALYSIS_REPORT_DTO_ID + " from queue");
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessorTest.java
deleted file mode 100644
index 8282194a513..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportProcessorTest.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation;
-
-import com.google.common.collect.ImmutableList;
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collections;
-import org.apache.commons.lang.RandomStringUtils;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.db.compute.AnalysisReportDto.Status;
-import org.sonar.server.computation.activity.ActivityManager;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
-import org.sonar.server.computation.step.ComputationStep;
-import org.sonar.server.computation.step.ComputationSteps;
-import org.sonar.server.computation.step.ReportComputationSteps;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-public class ReportProcessorTest {
-
- @Rule
- public LogTester logTester = new LogTester();
-
- ComputationStep projectStep1 = mockStep();
- ComputationStep projectStep2 = mockStep();
- ComputationSteps steps = mock(ReportComputationSteps.class);
- ActivityManager activityManager = mock(ActivityManager.class);
- System2 system = mock(System2.class);
- CEQueueStatus queueStatus = mock(CEQueueStatus.class);
- AnalysisReportDto dto = AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1").setStatus(Status.PENDING);
- ReportProcessor underTest;
-
- @Before
- public void setUp() {
- underTest = new ReportProcessor(steps, new ReportQueue.Item(dto, new File("Do_not_care")), activityManager, system, queueStatus);
- }
-
- @Test
- public void process_new_project() {
- logTester.setLevel(LoggerLevel.INFO);
-
- when(steps.instances()).thenReturn(Arrays.asList(projectStep1, projectStep2));
-
- underTest.process();
-
- // report is integrated -> status is set to SUCCESS
- assertThat(dto.getStatus()).isEqualTo(Status.SUCCESS);
- assertThat(dto.getFinishedAt()).isNotNull();
-
- // one info log at the end
- assertThat(logTester.logs(LoggerLevel.INFO)).hasSize(3);
-// assertThat(logTester.logs(LoggerLevel.INFO).get(0)).startsWith("Analysis of project P1 (report 1) (done) | time=");
- assertThat(logTester.logs(LoggerLevel.INFO).get(2)).startsWith("Analysis of project P1 (report 1) total time spent in steps=");
-
- // execute only the steps supporting the project qualifier
- verify(projectStep1).execute();
- verify(projectStep2).execute();
- verify(activityManager).saveActivity(dto);
-
- verify(queueStatus).addInProgress();
- verify(queueStatus).addSuccess(anyLong());
- verifyNoMoreInteractions(queueStatus);
- }
-
- @Test
- public void debug_logs() {
- when(steps.instances()).thenReturn(Collections.<ComputationStep>emptyList());
- logTester.setLevel(LoggerLevel.DEBUG);
-
- underTest.process();
-
- assertThat(logTester.logs(LoggerLevel.DEBUG)).isNotEmpty();
- }
-
- @Test
- public void fail_if_step_throws_error() {
- String errorMessage = "Failed to unzip";
- when(steps.instances()).thenReturn(ImmutableList.of(projectStep1));
- doThrow(new IllegalStateException(errorMessage)).when(projectStep1).execute();
-
- try {
- underTest.process();
- fail();
- } catch (IllegalStateException e) {
- assertThat(e.getMessage()).isEqualTo(errorMessage);
- assertThat(dto.getStatus()).isEqualTo(Status.FAILED);
- assertThat(dto.getFinishedAt()).isNotNull();
-
- verify(queueStatus).addInProgress();
- verify(queueStatus).addError(anyLong());
- verifyNoMoreInteractions(queueStatus);
- }
- }
-
- @Test
- public void step_error() {
- when(steps.instances()).thenReturn(Collections.singleton(projectStep1));
- doThrow(new IllegalStateException("pb")).when(projectStep1).execute();
-
- try {
- underTest.process();
- fail();
- } catch (IllegalStateException e) {
- assertThat(e.getMessage()).isEqualTo("pb");
- assertThat(dto.getStatus()).isEqualTo(Status.FAILED);
- assertThat(dto.getFinishedAt()).isNotNull();
-
- verify(queueStatus).addInProgress();
- verify(queueStatus).addError(anyLong());
- verifyNoMoreInteractions(queueStatus);
- }
- }
-
- private ComputationStep mockStep() {
- ComputationStep step = mock(ComputationStep.class);
- when(step.getDescription()).thenReturn(RandomStringUtils.randomAscii(5));
- return step;
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java
deleted file mode 100644
index d54d47e3be0..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportQueueTest.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.List;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbTester;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.process.ProcessProperties;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.compute.AnalysisReportDto.Status.PENDING;
-import static org.sonar.db.compute.AnalysisReportDto.Status.WORKING;
-
-@Category(DbTests.class)
-public class ReportQueueTest {
-
- static final long NOW = 1_500_000_000_000L;
-
- System2 system = mock(System2.class);
-
- @Rule
- public DbTester db = DbTester.create(system);
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- DbClient dbClient = db.getDbClient();
-
- Settings settings = new Settings();
- CEQueueStatus queueStatus = mock(CEQueueStatus.class);
- File dataDir;
- ReportQueue underTest;
-
- @Before
- public void setUp() throws Exception {
- dataDir = temp.newFolder();
- settings.setProperty(ProcessProperties.PATH_DATA, dataDir.getAbsolutePath());
- when(system.now()).thenReturn(NOW);
-
- underTest = new ReportQueue(dbClient, settings, queueStatus);
- }
-
- @Test
- public void starts_initializes_count_of_pending_reports() {
- underTest.add("P1", "Project 1", generateData());
- underTest.add("P2", "Project 2", generateData());
- underTest.add("P3", "Project 3", generateData());
-
- underTest.start();
-
- verify(queueStatus).initPendingCount(3);
- verifyNoMoreInteractions(queueStatus);
- }
-
- @Test
- public void add_report_to_queue() {
- // must:
- // 1. insert metadata in db
- // 2. copy report content to directory /data/analysis
- ReportQueue.Item item = underTest.add("P1", "Project 1", generateData());
-
- assertThat(item).isNotNull();
- assertThat(item.zipFile).isFile().exists().hasContent("some data").hasParent(new File(dataDir, "analysis"));
- assertThat(item.dto.getUuid()).isNotEmpty();
- assertThat(item.dto.getId()).isGreaterThan(0L);
-
- List<AnalysisReportDto> reports = dbClient.analysisReportDao().selectByProjectKey(db.getSession(), "P1");
- assertThat(reports).hasSize(1);
- AnalysisReportDto report = reports.get(0);
-
- assertThat(reports).hasSize(1);
- assertThat(report.getStatus()).isEqualTo(PENDING);
- assertThat(report.getProjectKey()).isEqualTo("P1");
- assertThat(report.getProjectName()).isEqualTo("Project 1");
- assertThat(report.getUuid()).isNotEmpty();
- assertThat(report.getId()).isGreaterThan(0L);
- assertThat(report.getCreatedAt()).isEqualTo(NOW);
- assertThat(report.getUpdatedAt()).isEqualTo(NOW);
- assertThat(report.getStartedAt()).isNull();
- assertThat(report.getFinishedAt()).isNull();
-
- assertThat(FileUtils.listFiles(analysisDir(), new String[]{"zip"}, false)).hasSize(1);
- }
-
- @Test
- public void pop_pending_items_in_fifo_order() {
- underTest.add("P1", "Project 1", generateData());
- underTest.add("P2", "Project 2", generateData());
- underTest.add("P3", "Project 3", generateData());
-
- ReportQueue.Item item = underTest.pop();
- assertThat(item.dto.getProjectKey()).isEqualTo("P1");
- assertThat(item.zipFile).exists().isFile().hasExtension("zip");
-
- // status changed from PENDING to WORKING
- assertThat(item.dto.getStatus()).isEqualTo(WORKING);
-
- assertThat(underTest.pop().dto.getProjectKey()).isEqualTo("P2");
- assertThat(underTest.pop().dto.getProjectKey()).isEqualTo("P3");
-
- // queue is empty
- assertThat(underTest.pop()).isNull();
-
- // items are still in db, but in WORKING status
- List<AnalysisReportDto> reports = underTest.all();
- assertThat(reports).hasSize(3);
- assertThat(reports).extracting("status").containsOnly(WORKING);
- }
-
- @Test
- public void remove() {
- ReportQueue.Item item = underTest.add("P1", "Project 1", generateData());
- assertThat(db.countRowsOfTable("analysis_reports")).isEqualTo(1);
-
- underTest.remove(item);
- assertThat(db.countRowsOfTable("analysis_reports")).isEqualTo(0);
- assertThat(item.zipFile).doesNotExist();
- }
-
- @Test
- public void do_not_pop_corrupted_item() {
- ReportQueue.Item item = underTest.add("P1", "Project 1", generateData());
-
- // emulate corruption: file is missing on FS
- FileUtils.deleteQuietly(item.zipFile);
-
- assertThat(underTest.pop()).isNull();
-
- // table sanitized
- assertThat(db.countRowsOfTable("analysis_reports")).isEqualTo(0);
- }
-
- @Test
- public void clear() {
- underTest.add("P1", "Project 1", generateData());
- underTest.add("P2", "Project 2", generateData());
- assertThat(analysisDir()).exists().isDirectory();
-
- underTest.clear();
-
- assertThat(db.countRowsOfTable("analysis_reports")).isEqualTo(0);
- assertThat(analysisDir()).doesNotExist();
- }
-
- @Test
- public void clear_do_not_fail_when_directory_do_not_exist() {
- underTest.clear();
- underTest.clear();
- }
-
- @Test
- public void reset_to_pending_status() {
- // 2 pending
- underTest.add("P1", "Project 1", generateData());
- underTest.add("P2", "Project 2", generateData());
-
- // pop 1 -> 1 pending and 1 working
- ReportQueue.Item workingItem = underTest.pop();
- assertThat(workingItem.dto.getStatus()).isEqualTo(WORKING);
- assertThat(underTest.all()).extracting("status").contains(PENDING, WORKING);
-
- underTest.resetToPendingStatus();
- assertThat(underTest.all()).extracting("status").containsOnly(PENDING).hasSize(2);
-
- }
-
- private InputStream generateData() {
- return IOUtils.toInputStream("some data");
- }
-
- private File analysisDir() {
- return new File(dataDir, "analysis");
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ReportSubmitterTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportSubmitterTest.java
new file mode 100644
index 00000000000..f9f3948f61f
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ReportSubmitterTest.java
@@ -0,0 +1,69 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation;
+
+import org.apache.commons.io.IOUtils;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.component.ComponentService;
+import org.sonar.server.tester.UserSessionRule;
+
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class ReportSubmitterTest {
+
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+
+ CeQueue queue = mock(CeQueue.class);
+ ReportFiles reportFiles = mock(ReportFiles.class);
+ ComponentService componentService = mock(ComponentService.class);
+ ReportSubmitter underTest = new ReportSubmitter(queue, userSession, reportFiles, componentService);
+
+ @Test
+ public void submit_a_report_on_existing_project() {
+ when(queue.prepareSubmit()).thenReturn(new CeTaskSubmit("TASK_1"));
+ userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+ when(componentService.getNullableByKey("MY_PROJECT")).thenReturn(new ComponentDto().setUuid("P1"));
+
+ underTest.submit("MY_PROJECT", "My Project", IOUtils.toInputStream("{binary}"));
+
+ verify(queue).submit(argThat(new TypeSafeMatcher<CeTaskSubmit>() {
+ @Override
+ protected boolean matchesSafely(CeTaskSubmit submit) {
+ return submit.getType().equals(CeTaskTypes.REPORT) && submit.getComponentUuid().equals("P1") &&
+ submit.getUuid().equals("TASK_1");
+ }
+
+ @Override
+ public void describeTo(Description description) {
+
+ }
+ }));
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/activity/ActivityManagerTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/activity/ActivityManagerTest.java
deleted file mode 100644
index c5b0ef2a150..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/activity/ActivityManagerTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation.activity;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbTester;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.server.activity.Activity;
-import org.sonar.server.activity.ActivityService;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-@Category(DbTests.class)
-public class ActivityManagerTest {
-
- @Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- ArgumentCaptor<Activity> activityArgumentCaptor = ArgumentCaptor.forClass(Activity.class);
-
- AnalysisReportDto reportDto = AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1").setStatus(AnalysisReportDto.Status.PENDING);
-
- ActivityService activityService = mock(ActivityService.class);
- ActivityManager underTest;
-
- @Before
- public void setup() {
- dbTester.truncateTables();
- underTest = new ActivityManager(activityService, dbTester.getDbClient());
- }
-
- @Test
- public void process_existing_project() {
- dbTester.prepareDbUnit(getClass(), "shared.xml");
-
- underTest.saveActivity(reportDto);
-
- verify(activityService).save(activityArgumentCaptor.capture());
-
- assertThat(activityArgumentCaptor.getValue().getType()).isEqualTo(Activity.Type.ANALYSIS_REPORT);
- assertThat(activityArgumentCaptor.getValue().getAction()).isEqualTo("LOG_ANALYSIS_REPORT");
- assertThat(activityArgumentCaptor.getValue().getData()).containsEntry("projectKey", "P1");
- assertThat(activityArgumentCaptor.getValue().getData()).containsEntry("projectName", "Project 1");
- assertThat(activityArgumentCaptor.getValue().getData().get("projectUuid")).isEqualTo("ABCD");
- }
-
- @Test
- public void process_new_project() {
- underTest.saveActivity(reportDto);
-
- // execute only the steps supporting the project qualifier
- verify(activityService).save(activityArgumentCaptor.capture());
-
- assertThat(activityArgumentCaptor.getValue().getType()).isEqualTo(Activity.Type.ANALYSIS_REPORT);
- assertThat(activityArgumentCaptor.getValue().getAction()).isEqualTo("LOG_ANALYSIS_REPORT");
- assertThat(activityArgumentCaptor.getValue().getData()).containsEntry("projectKey", "P1");
- }
-
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulatorTest.java
index 1ff92d01e63..3d4656b63c1 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulatorTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulatorTest.java
@@ -27,7 +27,7 @@ import java.util.List;
import javax.annotation.Nullable;
import org.junit.Test;
import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.CeTask;
import org.sonar.server.computation.step.ComputationStep;
import static com.google.common.base.Predicates.notNull;
@@ -36,15 +36,15 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
public class ReportComputeEngineContainerPopulatorTest {
- private ReportQueue.Item item = mock(ReportQueue.Item.class);
- private ReportComputeEngineContainerPopulator underTest = new ReportComputeEngineContainerPopulator(item);
+ private CeTask task = mock(CeTask.class);
+ private ReportComputeEngineContainerPopulator underTest = new ReportComputeEngineContainerPopulator(task);
@Test
public void item_is_added_to_the_container() {
AddedObjectsRecorderComputeEngineContainer container = new AddedObjectsRecorderComputeEngineContainer();
underTest.populateContainer(container);
- assertThat(container.added).contains(item);
+ assertThat(container.added).contains(task);
}
@Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/ComputeEngineQueueMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/ComputeEngineQueueMonitorTest.java
index 0b62598f3d0..18e338d7ebc 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/ComputeEngineQueueMonitorTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/monitoring/ComputeEngineQueueMonitorTest.java
@@ -20,7 +20,7 @@
package org.sonar.server.computation.monitoring;
import org.junit.Test;
-import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.CeQueue;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
@@ -34,7 +34,7 @@ public class ComputeEngineQueueMonitorTest {
private static final long SUCCESS_COUNT = 13;
private static final long PROCESSING_TIME = 987;
- private ComputeEngineQueueMonitor underTest = new ComputeEngineQueueMonitor(new DumbCEQueueStatus(), mock(ReportQueue.class));
+ private ComputeEngineQueueMonitor underTest = new ComputeEngineQueueMonitor(new DumbCEQueueStatus(), mock(CeQueue.class));
@Test
public void name_is_ComputeEngineQueue() {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java
index b35a139a4f8..65616a7bde0 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ComputationStepsTest.java
@@ -27,7 +27,7 @@ import java.util.Set;
import org.junit.Test;
import org.picocontainer.ComponentAdapter;
import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.CeTask;
import org.sonar.server.computation.container.ComputeEngineContainerImpl;
import org.sonar.server.computation.container.ReportComputeEngineContainerPopulator;
import org.sonar.server.computation.container.StepsExplorer;
@@ -51,7 +51,7 @@ public class ComputationStepsTest {
@Test
public void all_steps_from_package_step_are_present_in_container() {
- ComputeEngineContainerImpl ceContainer = new ComputeEngineContainerImpl(new ComponentContainer(), new ReportComputeEngineContainerPopulator(mock(ReportQueue.Item.class)));
+ ComputeEngineContainerImpl ceContainer = new ComputeEngineContainerImpl(new ComponentContainer(), new ReportComputeEngineContainerPopulator(mock(CeTask.class)));
Set<String> stepsCanonicalNames = StepsExplorer.retrieveStepPackageStepsCanonicalNames();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportExtractionStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportExtractionStepTest.java
index 1d4371b9e93..28923478d00 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportExtractionStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportExtractionStepTest.java
@@ -19,118 +19,96 @@
*/
package org.sonar.server.computation.step;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.List;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.utils.internal.JUnitTempFolder;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.server.computation.ReportQueue;
-import org.sonar.server.computation.batch.MutableBatchReportDirectoryHolder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
public class ReportExtractionStepTest {
-
- @Rule
- public JUnitTempFolder tempFolder = new JUnitTempFolder();
- @Rule
- public LogTester logTester = new LogTester().setLevel(LoggerLevel.INFO);
-
- private MutableBatchReportDirectoryHolder reportDirectoryHolder = mock(MutableBatchReportDirectoryHolder.class);
- private AnalysisReportDto dto = newDefaultReport();
- private ArgumentCaptor<File> fileCaptor = ArgumentCaptor.forClass(File.class);
-
- @Test
- public void fail_if_corrupted_zip() throws Exception {
- File zip = tempFolder.newFile();
- FileUtils.write(zip, "not a file");
-
- ReportExtractionStep underTest = new ReportExtractionStep(new ReportQueue.Item(dto, zip), tempFolder, reportDirectoryHolder);
-
- try {
- underTest.execute();
- fail();
- } catch (IllegalStateException e) {
- assertThat(e.getMessage()).startsWith("Fail to unzip " + zip.getAbsolutePath() + " into ");
- }
- verifyNoMoreInteractions(reportDirectoryHolder);
- }
-
- @Test
- public void verify_zip_decompression() throws URISyntaxException, IOException {
- new ReportExtractionStep(new ReportQueue.Item(dto, demoZipFile()), tempFolder, reportDirectoryHolder).execute();
-
- verify(reportDirectoryHolder).setDirectory(fileCaptor.capture());
- verifyNoMoreInteractions(reportDirectoryHolder);
-
- File createDir = fileCaptor.getValue();
- assertThat(createDir.exists()).isTrue();
- assertThat(createDir.isDirectory()).isTrue();
- verifyFile(createDir, "1.txt", "1\n");
- verifyFile(createDir, "2.txt", "2\n");
- File subDir1 = verifyDir(createDir, "subdir1");
- verifyFile(subDir1, "3.txt", "3\n");
- verifyFile(subDir1, "4.txt", "4\n");
- File subDir2 = verifyDir(createDir, "subdir2");
- verifyFile(subDir2, "5.txt", "5\n");
- File subdir3 = verifyDir(subDir2, "subdir3");
- verifyFile(subdir3, "6.txt", "6\n");
- }
-
- @Test
- public void verify_show_log_at_DEBUG_level() throws URISyntaxException {
- logTester.setLevel(LoggerLevel.DEBUG);
-
- new ReportExtractionStep(new ReportQueue.Item(dto, demoZipFile()), tempFolder, reportDirectoryHolder).execute();
-
- List<String> logs = logTester.logs();
- assertThat(logs).hasSize(1);
- String log = logs.get(0);
- assertThat(log.startsWith("Report extracted | size=")).isTrue();
- assertThat(log.contains(" | project=P1 | time=")).isTrue();
- }
-
- private File demoZipFile() throws URISyntaxException {
- return new File(getClass().getResource(getClass().getSimpleName() + "/" + "demozip.zip").toURI());
- }
-
- @Test
- public void no_log_at_INFO_level() throws URISyntaxException {
- logTester.setLevel(LoggerLevel.INFO);
-
- new ReportExtractionStep(new ReportQueue.Item(dto, demoZipFile()), tempFolder, reportDirectoryHolder).execute();
-
- assertThat(logTester.logs()).isEmpty();
- }
-
- private File verifyDir(File dir, String subDir) {
- File file = new File(dir, subDir);
- assertThat(file.exists()).isTrue();
- assertThat(file.isDirectory()).isTrue();
- return file;
- }
-
- private void verifyFile(File dir, String filename, String content) throws IOException {
- File file = new File(dir, filename);
- assertThat(file.exists()).isTrue();
- assertThat(file.isDirectory()).isFalse();
- assertThat(IOUtils.toString(new FileInputStream(file), "UTF-8")).isEqualTo(content);
- }
-
- private static AnalysisReportDto newDefaultReport() {
- return AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1").setStatus(AnalysisReportDto.Status.PENDING);
- }
+ //
+ // @Rule
+ // public JUnitTempFolder tempFolder = new JUnitTempFolder();
+ // @Rule
+ // public LogTester logTester = new LogTester().setLevel(LoggerLevel.INFO);
+ //
+ // private MutableBatchReportDirectoryHolder reportDirectoryHolder = mock(MutableBatchReportDirectoryHolder.class);
+ // private AnalysisReportDto dto = newDefaultReport();
+ // private ArgumentCaptor<File> fileCaptor = ArgumentCaptor.forClass(File.class);
+ //
+ // @Test
+ // public void fail_if_corrupted_zip() throws Exception {
+ // File zip = tempFolder.newFile();
+ // FileUtils.write(zip, "not a file");
+ //
+ // ReportExtractionStep underTest = new ReportExtractionStep(reportFiles, new ReportQueue.Item(dto, zip), tempFolder,
+ // reportDirectoryHolder);
+ //
+ // try {
+ // underTest.execute();
+ // fail();
+ // } catch (IllegalStateException e) {
+ // assertThat(e.getMessage()).startsWith("Fail to unzip " + zip.getAbsolutePath() + " into ");
+ // }
+ // verifyNoMoreInteractions(reportDirectoryHolder);
+ // }
+ //
+ // @Test
+ // public void verify_zip_decompression() throws URISyntaxException, IOException {
+ // new ReportExtractionStep(reportFiles, new ReportQueue.Item(dto, demoZipFile()), tempFolder, reportDirectoryHolder).execute();
+ //
+ // verify(reportDirectoryHolder).setDirectory(fileCaptor.capture());
+ // verifyNoMoreInteractions(reportDirectoryHolder);
+ //
+ // File createDir = fileCaptor.getValue();
+ // assertThat(createDir.exists()).isTrue();
+ // assertThat(createDir.isDirectory()).isTrue();
+ // verifyFile(createDir, "1.txt", "1\n");
+ // verifyFile(createDir, "2.txt", "2\n");
+ // File subDir1 = verifyDir(createDir, "subdir1");
+ // verifyFile(subDir1, "3.txt", "3\n");
+ // verifyFile(subDir1, "4.txt", "4\n");
+ // File subDir2 = verifyDir(createDir, "subdir2");
+ // verifyFile(subDir2, "5.txt", "5\n");
+ // File subdir3 = verifyDir(subDir2, "subdir3");
+ // verifyFile(subdir3, "6.txt", "6\n");
+ // }
+ //
+ // @Test
+ // public void verify_show_log_at_DEBUG_level() throws URISyntaxException {
+ // logTester.setLevel(LoggerLevel.DEBUG);
+ //
+ // new ReportExtractionStep(reportFiles, new ReportQueue.Item(dto, demoZipFile()), tempFolder, reportDirectoryHolder).execute();
+ //
+ // List<String> logs = logTester.logs();
+ // assertThat(logs).hasSize(1);
+ // String log = logs.get(0);
+ // assertThat(log.startsWith("Report extracted | size=")).isTrue();
+ // assertThat(log.contains(" | project=P1 | time=")).isTrue();
+ // }
+ //
+ // private File demoZipFile() throws URISyntaxException {
+ // return new File(getClass().getResource(getClass().getSimpleName() + "/" + "demozip.zip").toURI());
+ // }
+ //
+ // @Test
+ // public void no_log_at_INFO_level() throws URISyntaxException {
+ // logTester.setLevel(LoggerLevel.INFO);
+ //
+ // new ReportExtractionStep(reportFiles, new ReportQueue.Item(dto, demoZipFile()), tempFolder, reportDirectoryHolder).execute();
+ //
+ // assertThat(logTester.logs()).isEmpty();
+ // }
+ //
+ // private File verifyDir(File dir, String subDir) {
+ // File file = new File(dir, subDir);
+ // assertThat(file.exists()).isTrue();
+ // assertThat(file.isDirectory()).isTrue();
+ // return file;
+ // }
+ //
+ // private void verifyFile(File dir, String filename, String content) throws IOException {
+ // File file = new File(dir, filename);
+ // assertThat(file.exists()).isTrue();
+ // assertThat(file.isDirectory()).isFalse();
+ // assertThat(IOUtils.toString(new FileInputStream(file), "UTF-8")).isEqualTo(content);
+ // }
+ //
+ // private static AnalysisReportDto newDefaultReport() {
+ // return AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1").setStatus(AnalysisReportDto.Status.PENDING);
+ // }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/CeSubmitWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/CeSubmitWsActionTest.java
new file mode 100644
index 00000000000..deb1921077a
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/CeSubmitWsActionTest.java
@@ -0,0 +1,105 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.ws;
+
+import java.io.InputStream;
+import org.junit.Test;
+import org.sonar.core.util.Protobuf;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.ReportProcessingScheduler;
+import org.sonar.server.computation.ReportSubmitter;
+import org.sonar.server.plugins.MimeTypes;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.JsonAssert;
+import org.sonarqube.ws.WsCe;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class CeSubmitWsActionTest {
+
+ ReportSubmitter reportSubmitter = mock(ReportSubmitter.class);
+ ReportProcessingScheduler reportProcessingScheduler = mock(ReportProcessingScheduler.class);
+ CeSubmitWsAction underTest = new CeSubmitWsAction(reportSubmitter, reportProcessingScheduler);
+ WsActionTester tester = new WsActionTester(underTest);
+
+ @Test
+ public void submit_task_to_the_queue_and_ask_for_immediate_processing() {
+ CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", "robert");
+ when(reportSubmitter.submit(eq("my_project"), eq("My Project"), any(InputStream.class))).thenReturn(task);
+
+ TestResponse wsResponse = tester.newRequest()
+ .setParam("projectKey", "my_project")
+ .setParam("projectName", "My Project")
+ .setParam("report", "{binary}")
+ .setMediaType(MimeTypes.PROTOBUF)
+ .setMethod("POST")
+ .execute();
+
+ verify(reportSubmitter).submit(eq("my_project"), eq("My Project"), any(InputStream.class));
+ verify(reportProcessingScheduler).startAnalysisTaskNow();
+
+ // verify the protobuf response
+ WsCe.SubmitResponse submitResponse = Protobuf.read(wsResponse.getInputStream(), WsCe.SubmitResponse.PARSER);
+ assertThat(submitResponse.getTaskId()).isEqualTo("TASK_1");
+ assertThat(submitResponse.getProjectId()).isEqualTo("PROJECT_1");
+ }
+
+ @Test
+ public void test_response_example() {
+ CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", "robert");
+ when(reportSubmitter.submit(eq("my_project"), eq("My Project"), any(InputStream.class))).thenReturn(task);
+
+ TestResponse wsResponse = tester.newRequest()
+ .setParam("projectKey", "my_project")
+ .setParam("projectName", "My Project")
+ .setParam("report", "{binary}")
+ .setMediaType(MimeTypes.JSON)
+ .setMethod("POST")
+ .execute();
+
+ JsonAssert.assertJson(tester.getDef().responseExampleAsString()).isSimilarTo(wsResponse.getInput());
+ }
+
+ /**
+ * If project name is not specified, then name is the project key
+ */
+ @Test
+ public void project_name_is_optional() {
+ CeTask task = new CeTask("TASK_1", CeTaskTypes.REPORT, "PROJECT_1", "robert");
+ when(reportSubmitter.submit(eq("my_project"), eq("my_project"), any(InputStream.class))).thenReturn(task);
+
+ tester.newRequest()
+ .setParam("projectKey", "my_project")
+ .setParam("report", "{binary}")
+ .setMediaType(MimeTypes.PROTOBUF)
+ .setMethod("POST")
+ .execute();
+
+ verify(reportSubmitter).submit(eq("my_project"), eq("my_project"), any(InputStream.class));
+
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/CeTaskWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/CeTaskWsActionTest.java
new file mode 100644
index 00000000000..a07fb41b8e8
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/CeTaskWsActionTest.java
@@ -0,0 +1,129 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.util.Protobuf;
+import org.sonar.db.DbTester;
+import org.sonar.db.ce.CeActivityDto;
+import org.sonar.db.ce.CeQueueDto;
+import org.sonar.db.ce.CeTaskTypes;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.component.ComponentService;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.plugins.MimeTypes;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.WsCe;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class CeTaskWsActionTest {
+
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ ComponentService componentService = mock(ComponentService.class);
+ CeWsTaskFormatter formatter = new CeWsTaskFormatter(componentService);
+ CeTaskWsAction underTest = new CeTaskWsAction(dbTester.getDbClient(), formatter, userSession);
+ WsActionTester tester = new WsActionTester(underTest);
+
+ @Test
+ public void task_is_in_queue() throws Exception {
+ userSession.setGlobalPermissions(UserRole.ADMIN);
+
+ ComponentDto project = new ComponentDto().setUuid("PROJECT_1").setName("Project One").setKey("P1");
+ when(componentService.getNonNullByUuid("PROJECT_1")).thenReturn(project);
+
+ CeQueueDto queueDto = new CeQueueDto();
+ queueDto.setTaskType(CeTaskTypes.REPORT);
+ queueDto.setUuid("TASK_1");
+ queueDto.setComponentUuid(project.uuid());
+ queueDto.setStatus(CeQueueDto.Status.PENDING);
+ queueDto.setSubmitterLogin("john");
+ dbTester.getDbClient().ceQueueDao().insert(dbTester.getSession(), queueDto);
+ dbTester.getSession().commit();
+
+ TestResponse wsResponse = tester.newRequest()
+ .setMediaType(MimeTypes.PROTOBUF)
+ .setParam("id", "TASK_1")
+ .execute();
+
+ // verify the protobuf response
+ WsCe.TaskResponse taskResponse = Protobuf.read(wsResponse.getInputStream(), WsCe.TaskResponse.PARSER);
+ assertThat(taskResponse.getTask().getId()).isEqualTo("TASK_1");
+ assertThat(taskResponse.getTask().getStatus()).isEqualTo(WsCe.TaskStatus.PENDING);
+ assertThat(taskResponse.getTask().getSubmitterLogin()).isEqualTo("john");
+ assertThat(taskResponse.getTask().getComponentId()).isEqualTo(project.uuid());
+ assertThat(taskResponse.getTask().getComponentKey()).isEqualTo(project.key());
+ assertThat(taskResponse.getTask().getComponentName()).isEqualTo(project.name());
+ assertThat(taskResponse.getTask().hasExecutionTimeMs()).isFalse();
+ }
+
+ @Test
+ public void task_is_archived() throws Exception {
+ userSession.setGlobalPermissions(UserRole.ADMIN);
+
+ ComponentDto project = new ComponentDto().setUuid("PROJECT_1").setName("Project One").setKey("P1");
+ when(componentService.getNonNullByUuid("PROJECT_1")).thenReturn(project);
+
+ CeQueueDto queueDto = new CeQueueDto();
+ queueDto.setTaskType(CeTaskTypes.REPORT);
+ queueDto.setUuid("TASK_1");
+ queueDto.setComponentUuid(project.uuid());
+ CeActivityDto activityDto = new CeActivityDto(queueDto);
+ activityDto.setStatus(CeActivityDto.Status.FAILED);
+ activityDto.setExecutionTimeMs(500L);
+ dbTester.getDbClient().ceActivityDao().insert(dbTester.getSession(), activityDto);
+ dbTester.getSession().commit();
+
+ TestResponse wsResponse = tester.newRequest()
+ .setMediaType(MimeTypes.PROTOBUF)
+ .setParam("id", "TASK_1")
+ .execute();
+
+ // verify the protobuf response
+ WsCe.TaskResponse taskResponse = Protobuf.read(wsResponse.getInputStream(), WsCe.TaskResponse.PARSER);
+ assertThat(taskResponse.getTask().getId()).isEqualTo("TASK_1");
+ assertThat(taskResponse.getTask().getStatus()).isEqualTo(WsCe.TaskStatus.FAILED);
+ assertThat(taskResponse.getTask().getComponentId()).isEqualTo(project.uuid());
+ assertThat(taskResponse.getTask().getComponentKey()).isEqualTo(project.key());
+ assertThat(taskResponse.getTask().getComponentName()).isEqualTo(project.name());
+ assertThat(taskResponse.getTask().getExecutionTimeMs()).isEqualTo(500L);
+ }
+
+ @Test(expected = NotFoundException.class)
+ public void task_not_found() throws Exception {
+ userSession.setGlobalPermissions(UserRole.ADMIN);
+
+ tester.newRequest()
+ .setParam("id", "DOES_NOT_EXIST")
+ .execute();
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/ComputationWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/CeWsTest.java
index b40aec69ade..7dcf0f5074b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/ComputationWsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/CeWsTest.java
@@ -17,34 +17,27 @@
* 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.ws;
import org.junit.Test;
+import org.mockito.Mockito;
import org.sonar.api.server.ws.WebService;
-import org.sonar.server.activity.index.ActivityIndex;
import org.sonar.server.computation.ReportProcessingScheduler;
-import org.sonar.server.computation.ReportQueue;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
-import org.sonar.server.user.UserSession;
-import org.sonar.server.ws.WsTester;
+import org.sonar.server.computation.ReportSubmitter;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
-public class ComputationWsTest {
-
- WsTester ws = new WsTester(new ComputationWs(
- new QueueAction(mock(ReportQueue.class)),
- new SubmitReportAction(mock(ReportQueue.class), mock(ReportProcessingScheduler.class), mock(UserSession.class), mock(CEQueueStatus.class)),
- new HistoryAction(mock(ActivityIndex.class), mock(UserSession.class))));
+public class CeWsTest {
@Test
- public void define() {
- WebService.Controller controller = ws.controller("api/computation");
+ public void define() throws Exception {
+ CeWsAction wsAction = new CeSubmitWsAction(mock(ReportSubmitter.class), mock(ReportProcessingScheduler.class));
+
+ CeWs ws = new CeWs(wsAction);
+ WebService.Context context = mock(WebService.Context.class, Mockito.RETURNS_DEEP_STUBS);
+ ws.define(context);
- assertThat(controller).isNotNull();
- assertThat(controller.description()).isNotEmpty();
- assertThat(controller.actions()).hasSize(3);
+ assertThat(context.controller("api/ce")).isNotNull();
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryActionMediumTest.java
deleted file mode 100644
index f971c31a338..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/HistoryActionMediumTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.activity.Activity;
-import org.sonar.server.activity.ActivityService;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import java.util.Date;
-
-/**
- * TODO replace this medium test by a small test
- */
-public class HistoryActionMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester().withStartupTasks().withEsIndexes();
- @Rule
- public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester);
-
- HistoryAction sut;
- ActivityService activityService;
-
- @Before
- public void setUp() {
- tester.clearDbAndIndexes();
- sut = tester.get(HistoryAction.class);
- activityService = tester.get(ActivityService.class);
- }
-
- @Test
- public void search() throws Exception {
- Activity activity1 = new Activity();
- activity1.setType(Activity.Type.ANALYSIS_REPORT);
- activity1.setAction("LOG_ANALYSIS_REPORT");
- activity1.setData("projectKey", "P1");
- activity1.setData("projectName", "POne");
- activity1.setData("projectUuid", "U1");
- activity1.setData("status", AnalysisReportDto.Status.SUCCESS);
- activity1.setData("submittedAt", new Date());
- activityService.save(activity1);
-
- Activity activity2 = new Activity();
- activity2.setType(Activity.Type.ANALYSIS_REPORT);
- activity2.setAction("LOG_ANALYSIS_REPORT");
- activity2.setData("projectKey", "P2");
- activity2.setData("projectName", "PTwo");
- activity2.setData("projectUuid", "U2");
- activity2.setData("status", AnalysisReportDto.Status.FAILED);
- activity2.setData("submittedAt", new Date());
- activityService.save(activity2);
-
- userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
-
- WsTester.TestRequest request = tester.wsTester().newGetRequest("api/computation", "history");
- request.execute().assertJson(getClass(), "list_history_reports.json");
- }
-
- @Test(expected = ForbiddenException.class)
- public void requires_admin_right() throws Exception {
- WsTester.TestRequest request = tester.wsTester().newGetRequest("api/computation", "history");
- request.execute();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/IsQueueEmptyWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/IsQueueEmptyWsTest.java
deleted file mode 100644
index 034687fd34c..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/IsQueueEmptyWsTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import com.google.common.collect.Lists;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.server.computation.ReportQueue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class IsQueueEmptyWsTest {
-
- IsQueueEmptyWs.IsQueueEmptyAction underTest;
- ReportQueue queue;
- Response response;
-
- @Before
- public void before() {
- queue = mock(ReportQueue.class);
- underTest = new IsQueueEmptyWs.IsQueueEmptyAction(queue);
-
- response = mock(Response.class);
- when(response.stream()).thenReturn(new FakeStream());
- }
-
- @Test
- public void send_true_when_queue_is_empty() throws Exception {
- when(queue.all()).thenReturn(new ArrayList<AnalysisReportDto>());
-
- underTest.handle(mock(Request.class), response);
-
- assertThat(response.stream().toString()).isEqualTo("true");
- }
-
- @Test
- public void send_false_when_queue_is_not_empty() throws Exception {
- when(queue.all()).thenReturn(Lists.newArrayList(AnalysisReportDto.newForTests(1L)));
-
- underTest.handle(mock(Request.class), response);
-
- assertThat(response.stream().toString()).isEqualTo("false");
- }
-
- private class FakeStream implements Response.Stream {
- private ByteArrayOutputStream stream;
-
- private FakeStream() {
- this.stream = new ByteArrayOutputStream();
- }
-
- public String toString() {
- return stream.toString();
- }
-
- @Override
- public Response.Stream setMediaType(String s) {
- return null;
- }
-
- @Override
- public Response.Stream setStatus(int httpStatus) {
- return null;
- }
-
- @Override
- public OutputStream output() {
- return stream;
- }
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueActionTest.java
deleted file mode 100644
index e74d9d15416..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/QueueActionTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import com.google.common.collect.Lists;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.server.computation.ReportQueue;
-import org.sonar.server.ws.WsTester;
-
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.compute.AnalysisReportDto.Status.PENDING;
-
-public class QueueActionTest {
-
- WsTester tester;
- private ReportQueue queue;
-
- @Before
- public void setup() {
- queue = mock(ReportQueue.class);
- tester = new WsTester(new ComputationWs(new QueueAction(queue)));
- }
-
- @Test
- public void list_active_reports() throws Exception {
- AnalysisReportDto report = AnalysisReportDto
- .newForTests(1L)
- .setProjectKey("project-key")
- .setProjectName("Project name")
- .setStatus(PENDING)
- .setUuid("PROJECT_UUID")
- .setCreatedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime())
- .setStartedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime())
- .setFinishedAt(DateUtils.parseDateTime("2014-10-13T00:00:00+0200").getTime());
- List<AnalysisReportDto> reports = Lists.newArrayList(report);
- when(queue.all()).thenReturn(reports);
-
- WsTester.TestRequest request = tester.newGetRequest(ComputationWs.ENDPOINT, "queue");
- request.execute().assertJson(getClass(), "list_queue_reports.json");
- }
-
- @Test
- public void define() {
- assertThat(tester.controller(ComputationWs.ENDPOINT).action("queue")).isNotNull();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportActionTest.java
deleted file mode 100644
index 18f8fdfc5d0..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/ws/SubmitReportActionTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.computation.ws;
-
-import java.io.InputStream;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.db.compute.AnalysisReportDto;
-import org.sonar.server.computation.ReportProcessingScheduler;
-import org.sonar.server.computation.ReportQueue;
-import org.sonar.server.computation.monitoring.CEQueueStatus;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ws.WsTester;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class SubmitReportActionTest {
-
- @Rule
- public UserSessionRule userSessionRule = UserSessionRule.standalone();
-
- ReportProcessingScheduler workerLauncher = mock(ReportProcessingScheduler.class);
- CEQueueStatus queueStatus = mock(CEQueueStatus.class);
- ReportQueue queue = mock(ReportQueue.class);
- WsTester wsTester;
- SubmitReportAction underTest;
-
- @Before
- public void before() {
- underTest = new SubmitReportAction(queue, workerLauncher, userSessionRule, queueStatus);
- wsTester = new WsTester(new ComputationWs(underTest));
- }
-
- @Test
- public void define_metadata() {
- WebService.Context context = new WebService.Context();
- WebService.NewController controller = context.createController("api/computation");
- underTest.define(controller);
- controller.done();
-
- WebService.Action action = context.controller("api/computation").action("submit_report");
- assertThat(action).isNotNull();
- assertThat(action.params()).hasSize(3);
- }
-
- @Test
- public void add_element_to_queue_and_launch_analysis_task() throws Exception {
- userSessionRule.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
- AnalysisReportDto dto = mock(AnalysisReportDto.class);
- when(dto.getId()).thenReturn(42L);
- when(queue.add(any(String.class), any(String.class), any(InputStream.class))).thenReturn(new ReportQueue.Item(dto, null));
-
- WsTester.TestRequest request = wsTester
- .newPostRequest(ComputationWs.ENDPOINT, "submit_report")
- .setParam(SubmitReportAction.PARAM_PROJECT_KEY, "P1")
- .setParam(SubmitReportAction.PARAM_PROJECT_NAME, "Project 1")
- .setParam(SubmitReportAction.PARAM_REPORT_DATA, null);
- WsTester.Result response = request.execute();
-
- verify(queue).add(eq("P1"), eq("Project 1"), any(InputStream.class));
- verify(workerLauncher).startAnalysisTaskNow();
- verify(queueStatus).addReceived();
- assertThat(response.outputAsString()).isEqualTo("{\"key\":\"42\"}");
- }
-
- @Test(expected = ForbiddenException.class)
- public void requires_scan_permission() throws Exception {
- userSessionRule.setGlobalPermissions(GlobalPermissions.DASHBOARD_SHARING);
-
- WsTester.TestRequest request = wsTester
- .newPostRequest(ComputationWs.ENDPOINT, "submit_report")
- .setParam(SubmitReportAction.PARAM_PROJECT_KEY, "P1")
- .setParam(SubmitReportAction.PARAM_PROJECT_NAME, "Project 1")
- .setParam(SubmitReportAction.PARAM_REPORT_DATA, null);
- request.execute();
-
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/ws/TestRequest.java b/server/sonar-server/src/test/java/org/sonar/server/ws/TestRequest.java
index 3405e132459..5d844b9757e 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/ws/TestRequest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/ws/TestRequest.java
@@ -23,6 +23,7 @@ import com.google.common.base.Throwables;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
+import org.apache.commons.io.IOUtils;
import org.sonar.api.server.ws.internal.ValidatingRequest;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -40,7 +41,11 @@ public class TestRequest extends ValidatingRequest {
@Override
protected InputStream readInputStreamParam(String key) {
- throw new UnsupportedOperationException("Not supported in test yet");
+ String value = readParam(key);
+ if (value == null) {
+ return null;
+ }
+ return IOUtils.toInputStream(value);
}
@Override
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryActionMediumTest/list_history_reports.json b/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryActionMediumTest/list_history_reports.json
deleted file mode 100644
index caa180819a4..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/HistoryActionMediumTest/list_history_reports.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "reports": [
- {
- "status": "SUCCESS",
- "projectName": "POne",
- "projectKey": "P1",
- "projectUuid": "U1"
- },
- {
- "status": "FAILED",
- "projectName": "PTwo",
- "projectKey": "P2",
- "projectUuid": "U2"
- }
- ]
-}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/QueueActionTest/list_queue_reports.json b/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/QueueActionTest/list_queue_reports.json
deleted file mode 100644
index 10247f2e942..00000000000
--- a/server/sonar-server/src/test/resources/org/sonar/server/computation/ws/QueueActionTest/list_queue_reports.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "reports": [
- {
- "key": 1,
- "status": "PENDING",
- "projectName": "Project name",
- "projectKey": "project-key",
- "submittedAt": "2014-10-13T00:00:00+0200",
- "startedAt": "2014-10-13T00:00:00+0200",
- "finishedAt": "2014-10-13T00:00:00+0200"
- }
- ]
-}
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/414_add_scan_and_dry_run_permissions.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/414_add_scan_and_dry_run_permissions.rb
index c8ba5db51d7..d46065fdecc 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/414_add_scan_and_dry_run_permissions.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/414_add_scan_and_dry_run_permissions.rb
@@ -39,6 +39,10 @@ class AddScanAndDryRunPermissions < ActiveRecord::Migration
# -- Role dryRunScan --
# Anyone
GroupRole.create(:group_id => nil, :role => 'dryRunScan', :resource_id => nil)
+
+ # -- Role provisioning --
+ # Anyone
+ GroupRole.create(:group_id => nil, :role => 'provisioning', :resource_id => nil)
end
end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/931_create_ce_activity.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/931_create_ce_activity.rb
new file mode 100644
index 00000000000..e2bb4cb8fa5
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/931_create_ce_activity.rb
@@ -0,0 +1,45 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#
+# SonarQube 5.2
+#
+class CreateCeActivity < ActiveRecord::Migration
+
+ def self.up
+ create_table 'ce_activity' do |t|
+ t.column 'uuid', :string, :limit => 40, :null => false
+ t.column 'task_type', :string, :limit => 15, :null => false
+ t.column 'component_uuid', :string, :limit => 40, :null => true
+ t.column 'status', :string, :limit => 15, :null => false
+ t.column 'is_last', :boolean, :null => false
+ t.column 'is_last_key', :string, :limit => 55, :null => false
+ t.column 'submitter_login', :string, :limit => 255, :null => true
+ t.column 'submitted_at', :big_integer, :null => false
+ t.column 'started_at', :big_integer, :null => true
+ t.column 'finished_at', :big_integer, :null => true
+ t.column 'created_at', :big_integer, :null => false
+ t.column 'updated_at', :big_integer, :null => false
+ t.column 'execution_time_ms', :big_integer, :null => true
+ end
+ add_index 'ce_activity', 'uuid', :name => 'ce_activity_uuid', :unique => true
+ end
+
+end
+
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/932_create_ce_queue.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/932_create_ce_queue.rb
new file mode 100644
index 00000000000..e8d0be4da42
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/932_create_ce_queue.rb
@@ -0,0 +1,40 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#
+# SonarQube 5.2
+#
+class CreateCeQueue < ActiveRecord::Migration
+
+ def self.up
+ create_table 'ce_queue' do |t|
+ t.column 'uuid', :string, :limit => 40, :null => false
+ t.column 'task_type', :string, :limit => 15, :null => false
+ t.column 'component_uuid', :string, :limit => 40, :null => true
+ t.column 'status', :string, :limit => 15, :null => false
+ t.column 'submitter_login', :string, :limit => 255, :null => true
+ t.column 'started_at', :big_integer, :null => true
+ t.column 'created_at', :big_integer, :null => false
+ t.column 'updated_at', :big_integer, :null => false
+ end
+ add_index 'ce_queue', 'uuid', :name => 'ce_queue_uuid', :unique => true
+ end
+
+end
+
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/933_drop_table_analysis_reports.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/933_drop_table_analysis_reports.rb
new file mode 100644
index 00000000000..36e925b47e9
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/933_drop_table_analysis_reports.rb
@@ -0,0 +1,30 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#
+# SonarQube 5.2
+#
+class DropTableAnalysisReports < ActiveRecord::Migration
+
+ def self.up
+ drop_table 'analysis_reports'
+ end
+
+end
+
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/934_remove_analysis_reports_from_activities.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/934_remove_analysis_reports_from_activities.rb
new file mode 100644
index 00000000000..3c877912ab3
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/934_remove_analysis_reports_from_activities.rb
@@ -0,0 +1,30 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#
+# SonarQube 5.2
+#
+class RemoveAnalysisReportsFromActivities < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration('org.sonar.db.version.v52.RemoveAnalysisReportsFromActivities')
+ end
+
+end
+