+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation;
-
-import java.util.Arrays;
-import java.util.List;
-import org.sonar.core.issue.db.UpdateConflictResolver;
-import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.activity.CEActivityManager;
-import org.sonar.server.computation.batch.CEBatchReportReader;
-import org.sonar.server.computation.batch.ReportExtractor;
-import org.sonar.server.computation.component.DbComponentsRefCache;
-import org.sonar.server.computation.component.ProjectSettingsRepository;
-import org.sonar.server.computation.container.CEContainer;
-import org.sonar.server.computation.issue.IssueCache;
-import org.sonar.server.computation.issue.IssueComputation;
-import org.sonar.server.computation.issue.RuleCache;
-import org.sonar.server.computation.issue.RuleCacheLoader;
-import org.sonar.server.computation.issue.ScmAccountCache;
-import org.sonar.server.computation.issue.ScmAccountCacheLoader;
-import org.sonar.server.computation.issue.SourceLinesCache;
-import org.sonar.server.computation.language.PlatformLanguageRepository;
-import org.sonar.server.computation.measure.MetricCache;
-import org.sonar.server.computation.step.ComputationSteps;
-import org.sonar.server.platform.Platform;
-import org.sonar.server.view.index.ViewIndex;
-
-public class ComputationContainer {
-
- /**
- * List of all objects to be injected in the picocontainer dedicated to computation stack.
- * Does not contain the steps declared in {@link org.sonar.server.computation.step.ComputationSteps#orderedStepClasses()}.
- */
- static List componentClasses() {
- return Arrays.asList(
- CEActivityManager.class,
- ReportExtractor.class,
- CEBatchReportReader.class,
-
- // repositories
- PlatformLanguageRepository.class,
- ProjectSettingsRepository.class,
-
- // component caches
- DbComponentsRefCache.class,
-
- // issues
- ScmAccountCacheLoader.class,
- ScmAccountCache.class,
- SourceLinesCache.class,
- IssueComputation.class,
- RuleCache.class,
- RuleCacheLoader.class,
- IssueCache.class,
- MetricCache.class,
- UpdateConflictResolver.class,
-
- // views
- ViewIndex.class);
- }
-
- public void execute(ReportQueue.Item item) {
- ComponentContainer container = Platform.getInstance().getContainer();
-
- ComponentContainer ceContainer = new CEContainer(container);
- ceContainer.add(ceContainer);
- ceContainer.add(item);
- ceContainer.addSingletons(componentClasses());
- ceContainer.addSingletons(ComputationSteps.orderedStepClasses());
- try {
- ceContainer.getComponentByType(ComputationService.class).process();
- } finally {
- ceContainer.stopComponents();
- // TODO not possible to have multiple children -> will be
- // a problem when we will have multiple concurrent computation workers
- container.removeChild();
- }
- }
-
-}
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.activity.CEActivityManager;
+import org.sonar.server.computation.activity.ActivityManager;
import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.component.ComponentTreeBuilders;
import org.sonar.server.computation.language.LanguageRepository;
private final ReportQueue.Item item;
private final ComputationSteps steps;
private final BatchReportReader reportReader;
- private final CEActivityManager activityManager;
+ private final ActivityManager activityManager;
private final System2 system;
private final DbClient dbClient;
private final LanguageRepository languageRepository;
- public ComputationService(ReportQueue.Item item, ComputationSteps steps, CEActivityManager activityManager, System2 system,
+ public ComputationService(ReportQueue.Item item, ComputationSteps steps, ActivityManager activityManager, System2 system,
BatchReportReader reportReader, DbClient dbClient, LanguageRepository languageRepository) {
this.item = item;
this.steps = steps;
package org.sonar.server.computation;
-import com.google.common.annotations.VisibleForTesting;
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.ComputeEngineContainer;
+import org.sonar.server.computation.container.ContainerFactory;
/**
* This thread pops a report from the queue and integrate it.
private static final Logger LOG = Loggers.get(ComputationThread.class);
private final ReportQueue queue;
- private final ComputationContainer container;
+ private final ComponentContainer sqContainer;
+ private final ContainerFactory containerFactory;
- public ComputationThread(ReportQueue queue) {
+ public ComputationThread(ReportQueue queue, ComponentContainer sqContainer, ContainerFactory containerFactory) {
this.queue = queue;
- this.container = new ComputationContainer();
- }
-
- @VisibleForTesting
- ComputationThread(ReportQueue queue, ComputationContainer container) {
- this.queue = queue;
- this.container = container;
+ this.sqContainer = sqContainer;
+ this.containerFactory = containerFactory;
}
@Override
} catch (Exception e) {
LOG.error("Failed to pop the queue of analysis reports", e);
}
- if (item != null) {
- try {
- container.execute(item);
- } catch (Throwable e) {
- LOG.error(String.format(
- "Failed to process analysis report %d of project %s", item.dto.getId(), item.dto.getProjectKey()), e);
- } finally {
- removeSilentlyFromQueue(item);
- }
+ if (item == null) {
+ return;
+ }
+
+ ComputeEngineContainer computeEngineContainer = containerFactory.create(sqContainer, item);
+ try {
+ computeEngineContainer.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);
}
}
import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import org.picocontainer.Startable;
-import org.sonar.api.platform.Server;
-import org.sonar.api.platform.ServerStartHandler;
-
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
+import org.picocontainer.Startable;
+import org.sonar.api.platform.Server;
+import org.sonar.api.platform.ServerStartHandler;
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.server.computation.container.ContainerFactory;
+import org.sonar.server.computation.container.ContainerFactoryImpl;
public class ComputationThreadLauncher implements Startable, ServerStartHandler {
public static final String THREAD_NAME_PREFIX = "computation-";
private final ReportQueue queue;
+ private final ComponentContainer sqContainer;
private final ScheduledExecutorService executorService;
+ private final ContainerFactory containerFactory;
private final long delayBetweenTasks;
private final long delayForFirstStart;
private final TimeUnit timeUnit;
- public ComputationThreadLauncher(ReportQueue queue) {
+ public ComputationThreadLauncher(ReportQueue queue, ComponentContainer sqContainer) {
this.queue = queue;
+ this.sqContainer = sqContainer;
this.executorService = Executors.newSingleThreadScheduledExecutor(newThreadFactory());
+ this.containerFactory = new ContainerFactoryImpl();
this.delayBetweenTasks = 10;
this.delayForFirstStart = 0;
}
@VisibleForTesting
- ComputationThreadLauncher(ReportQueue queue, long delayForFirstStart, long delayBetweenTasks, TimeUnit timeUnit) {
+ ComputationThreadLauncher(ReportQueue queue, ComponentContainer sqContainer, ContainerFactory containerFactory,
+ long delayForFirstStart, long delayBetweenTasks, TimeUnit timeUnit) {
this.queue = queue;
+ this.sqContainer = sqContainer;
+ this.containerFactory = containerFactory;
this.executorService = Executors.newSingleThreadScheduledExecutor(newThreadFactory());
this.delayBetweenTasks = delayBetweenTasks;
}
public void startAnalysisTaskNow() {
- executorService.execute(new ComputationThread(queue));
+ executorService.execute(new ComputationThread(queue, sqContainer, containerFactory));
}
@Override
public void onServerStart(Server server) {
- executorService.scheduleAtFixedRate(new ComputationThread(queue), delayForFirstStart, delayBetweenTasks, timeUnit);
+ executorService.scheduleAtFixedRate(new ComputationThread(queue, sqContainer, containerFactory), delayForFirstStart, delayBetweenTasks, timeUnit);
}
private ThreadFactory newThreadFactory() {
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.activity;
+
+import javax.annotation.CheckForNull;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.activity.Activity;
+import org.sonar.server.activity.ActivityService;
+import org.sonar.server.db.DbClient;
+
+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) {
+ ComponentDto project = 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 (project != null) {
+ activity
+ .setData("projectName", project.name())
+ .setData("projectUuid", project.uuid());
+ }
+ activityService.save(activity);
+ }
+
+ @CheckForNull
+ private ComponentDto loadProject(String projectKey) {
+ DbSession session = dbClient.openSession(false);
+ try {
+ return dbClient.componentDao().selectNullableByKey(session, projectKey);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation.activity;
-
-import javax.annotation.CheckForNull;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.server.activity.Activity;
-import org.sonar.server.activity.ActivityService;
-import org.sonar.server.db.DbClient;
-
-import static org.sonar.api.utils.DateUtils.formatDateTimeNullSafe;
-import static org.sonar.api.utils.DateUtils.longToDate;
-
-public class CEActivityManager {
- private final ActivityService activityService;
- private final DbClient dbClient;
-
- public CEActivityManager(ActivityService activityService, DbClient dbClient) {
- this.activityService = activityService;
- this.dbClient = dbClient;
- }
-
- public void saveActivity(AnalysisReportDto report) {
- ComponentDto project = 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 (project != null) {
- activity
- .setData("projectName", project.name())
- .setData("projectUuid", project.uuid());
- }
- activityService.save(activity);
- }
-
- @CheckForNull
- private ComponentDto loadProject(String projectKey) {
- DbSession session = dbClient.openSession(false);
- try {
- return dbClient.componentDao().selectNullableByKey(session, projectKey);
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.batch;
+
+import com.google.common.base.Throwables;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.Parser;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.NoSuchElementException;
+import javax.annotation.CheckForNull;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.LineIterator;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.util.CloseableIterator;
+
+public class BatchReportReaderImpl implements BatchReportReader {
+ private final org.sonar.batch.protocol.output.BatchReportReader delegate;
+
+ public BatchReportReaderImpl(ReportExtractor reportExtractor, ReportQueue.Item item) {
+ this.delegate = new org.sonar.batch.protocol.output.BatchReportReader(reportExtractor.extractReportInDir(item));
+ }
+
+ @Override
+ public BatchReport.Metadata readMetadata() {
+ return delegate.readMetadata();
+ }
+
+ @Override
+ public List<BatchReport.Measure> readComponentMeasures(int componentRef) {
+ return delegate.readComponentMeasures(componentRef);
+ }
+
+ @Override
+ @CheckForNull
+ public BatchReport.Changesets readChangesets(int componentRef) {
+ return delegate.readChangesets(componentRef);
+ }
+
+ @Override
+ public BatchReport.Component readComponent(int componentRef) {
+ return delegate.readComponent(componentRef);
+ }
+
+ @Override
+ public List<BatchReport.Issue> readComponentIssues(int componentRef) {
+ return delegate.readComponentIssues(componentRef);
+ }
+
+ @Override
+ public BatchReport.Issues readDeletedComponentIssues(int deletedComponentRef) {
+ return delegate.readDeletedComponentIssues(deletedComponentRef);
+ }
+
+ @Override
+ public List<BatchReport.Duplication> readComponentDuplications(int componentRef) {
+ return delegate.readComponentDuplications(componentRef);
+ }
+
+ @Override
+ public List<BatchReport.Symbols.Symbol> readComponentSymbols(int componentRef) {
+ return delegate.readComponentSymbols(componentRef);
+ }
+
+ @Override
+ @CheckForNull
+ public CloseableIterator<BatchReport.SyntaxHighlighting> readComponentSyntaxHighlighting(int fileRef) {
+ File file = delegate.readComponentSyntaxHighlighting(fileRef);
+ if (file == null) {
+ return CloseableIterator.emptyCloseableIterator();
+ }
+
+ try {
+ return new ParserCloseableIterator<>(BatchReport.SyntaxHighlighting.PARSER, FileUtils.openInputStream(file));
+ } catch (IOException e) {
+ Throwables.propagate(e);
+ // actually never reached
+ return CloseableIterator.emptyCloseableIterator();
+ }
+ }
+
+ @Override
+ public CloseableIterator<BatchReport.Coverage> readComponentCoverage(int fileRef) {
+ File file = delegate.readComponentCoverage(fileRef);
+ if (file == null) {
+ return CloseableIterator.emptyCloseableIterator();
+ }
+
+ try {
+ return new ParserCloseableIterator<>(BatchReport.Coverage.PARSER, FileUtils.openInputStream(file));
+ } catch (IOException e) {
+ Throwables.propagate(e);
+ // actually never reached
+ return CloseableIterator.emptyCloseableIterator();
+ }
+ }
+
+ @Override
+ public CloseableIterator<String> readFileSource(int fileRef) {
+ File file = delegate.readFileSource(fileRef);
+ if (file == null) {
+ throw new IllegalStateException("Unable to find source for file #" + fileRef + ". File does not exist: " + file);
+ }
+
+ try {
+ final LineIterator lineIterator = IOUtils.lineIterator(FileUtils.openInputStream(file), StandardCharsets.UTF_8);
+ return new CloseableIterator<String>() {
+ @Override
+ public boolean hasNext() {
+ return lineIterator.hasNext();
+ }
+
+ @Override
+ public String next() {
+ return lineIterator.next();
+ }
+
+ @Override
+ protected String doNext() {
+ // never called anyway
+ throw new NoSuchElementException("Empty closeable Iterator has no element");
+ }
+
+ @Override
+ protected void doClose() throws Exception {
+ lineIterator.close();
+ }
+ };
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to traverse file: " + file, e);
+ }
+ }
+
+ @Override
+ public CloseableIterator<BatchReport.Test> readTests(int testFileRef) {
+ File file = delegate.readTests(testFileRef);
+ if (file == null) {
+ return CloseableIterator.emptyCloseableIterator();
+ }
+
+ try {
+ return new ParserCloseableIterator<>(BatchReport.Test.PARSER, FileUtils.openInputStream(file));
+ } catch (IOException e) {
+ Throwables.propagate(e);
+ // actually never reached
+ return CloseableIterator.emptyCloseableIterator();
+ }
+ }
+
+ @Override
+ public CloseableIterator<BatchReport.CoverageDetail> readCoverageDetails(int testFileRef) {
+ File file = delegate.readCoverageDetails(testFileRef);
+ if (file == null) {
+ return CloseableIterator.emptyCloseableIterator();
+ }
+
+ try {
+ return new ParserCloseableIterator<>(BatchReport.CoverageDetail.PARSER, FileUtils.openInputStream(file));
+ } catch (IOException e) {
+ Throwables.propagate(e);
+ // actually never reached
+ return CloseableIterator.emptyCloseableIterator();
+ }
+ }
+
+ private static class ParserCloseableIterator<T> extends CloseableIterator<T> {
+ private final Parser<T> parser;
+ private final FileInputStream fileInputStream;
+
+ public ParserCloseableIterator(Parser<T> parser, FileInputStream fileInputStream) {
+ this.parser = parser;
+ this.fileInputStream = fileInputStream;
+ }
+
+ @Override
+ protected T doNext() {
+ try {
+ return parser.parseDelimitedFrom(fileInputStream);
+ } catch (InvalidProtocolBufferException e) {
+ Throwables.propagate(e);
+ // actually never reached
+ return null;
+ }
+ }
+
+ @Override
+ protected void doClose() throws Exception {
+ fileInputStream.close();
+ }
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation.batch;
-
-import com.google.common.base.Throwables;
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.protobuf.Parser;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import javax.annotation.CheckForNull;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.LineIterator;
-import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.server.computation.ReportQueue;
-import org.sonar.server.util.CloseableIterator;
-
-public class CEBatchReportReader implements BatchReportReader {
- private final org.sonar.batch.protocol.output.BatchReportReader delegate;
-
- public CEBatchReportReader(ReportExtractor reportExtractor, ReportQueue.Item item) {
- this.delegate = new org.sonar.batch.protocol.output.BatchReportReader(reportExtractor.extractReportInDir(item));
- }
-
- @Override
- public BatchReport.Metadata readMetadata() {
- return delegate.readMetadata();
- }
-
- @Override
- public List<BatchReport.Measure> readComponentMeasures(int componentRef) {
- return delegate.readComponentMeasures(componentRef);
- }
-
- @Override
- @CheckForNull
- public BatchReport.Changesets readChangesets(int componentRef) {
- return delegate.readChangesets(componentRef);
- }
-
- @Override
- public BatchReport.Component readComponent(int componentRef) {
- return delegate.readComponent(componentRef);
- }
-
- @Override
- public List<BatchReport.Issue> readComponentIssues(int componentRef) {
- return delegate.readComponentIssues(componentRef);
- }
-
- @Override
- public BatchReport.Issues readDeletedComponentIssues(int deletedComponentRef) {
- return delegate.readDeletedComponentIssues(deletedComponentRef);
- }
-
- @Override
- public List<BatchReport.Duplication> readComponentDuplications(int componentRef) {
- return delegate.readComponentDuplications(componentRef);
- }
-
- @Override
- public List<BatchReport.Symbols.Symbol> readComponentSymbols(int componentRef) {
- return delegate.readComponentSymbols(componentRef);
- }
-
- @Override
- @CheckForNull
- public CloseableIterator<BatchReport.SyntaxHighlighting> readComponentSyntaxHighlighting(int fileRef) {
- File file = delegate.readComponentSyntaxHighlighting(fileRef);
- if (file == null) {
- return CloseableIterator.emptyCloseableIterator();
- }
-
- try {
- return new ParserCloseableIterator<>(BatchReport.SyntaxHighlighting.PARSER, FileUtils.openInputStream(file));
- } catch (IOException e) {
- Throwables.propagate(e);
- // actually never reached
- return CloseableIterator.emptyCloseableIterator();
- }
- }
-
- @Override
- public CloseableIterator<BatchReport.Coverage> readComponentCoverage(int fileRef) {
- File file = delegate.readComponentCoverage(fileRef);
- if (file == null) {
- return CloseableIterator.emptyCloseableIterator();
- }
-
- try {
- return new ParserCloseableIterator<>(BatchReport.Coverage.PARSER, FileUtils.openInputStream(file));
- } catch (IOException e) {
- Throwables.propagate(e);
- // actually never reached
- return CloseableIterator.emptyCloseableIterator();
- }
- }
-
- @Override
- public CloseableIterator<String> readFileSource(int fileRef) {
- File file = delegate.readFileSource(fileRef);
- if (file == null) {
- throw new IllegalStateException("Unable to find source for file #" + fileRef + ". File does not exist: " + file);
- }
-
- try {
- final LineIterator lineIterator = IOUtils.lineIterator(FileUtils.openInputStream(file), StandardCharsets.UTF_8);
- return new CloseableIterator<String>() {
- @Override
- public boolean hasNext() {
- return lineIterator.hasNext();
- }
-
- @Override
- protected String doNext() {
- return lineIterator.next();
- }
-
- @Override
- protected void doClose() throws Exception {
- lineIterator.close();
- }
- };
- } catch (IOException e) {
- throw new IllegalStateException("Fail to traverse file: " + file, e);
- }
- }
-
- @Override
- public CloseableIterator<BatchReport.Test> readTests(int testFileRef) {
- File file = delegate.readTests(testFileRef);
- if (file == null) {
- return CloseableIterator.emptyCloseableIterator();
- }
-
- try {
- return new ParserCloseableIterator<>(BatchReport.Test.PARSER, FileUtils.openInputStream(file));
- } catch (IOException e) {
- Throwables.propagate(e);
- // actually never reached
- return CloseableIterator.emptyCloseableIterator();
- }
- }
-
- @Override
- public CloseableIterator<BatchReport.CoverageDetail> readCoverageDetails(int testFileRef) {
- File file = delegate.readCoverageDetails(testFileRef);
- if (file == null) {
- return CloseableIterator.emptyCloseableIterator();
- }
-
- try {
- return new ParserCloseableIterator<>(BatchReport.CoverageDetail.PARSER, FileUtils.openInputStream(file));
- } catch (IOException e) {
- Throwables.propagate(e);
- // actually never reached
- return CloseableIterator.emptyCloseableIterator();
- }
- }
-
- private static class ParserCloseableIterator<T> extends CloseableIterator<T> {
- private final Parser<T> parser;
- private final FileInputStream fileInputStream;
-
- public ParserCloseableIterator(Parser<T> parser, FileInputStream fileInputStream) {
- this.parser = parser;
- this.fileInputStream = fileInputStream;
- }
-
- @Override
- protected T doNext() {
- try {
- return parser.parseDelimitedFrom(fileInputStream);
- } catch (InvalidProtocolBufferException e) {
- Throwables.propagate(e);
- // actually never reached
- return null;
- }
- }
-
- @Override
- protected void doClose() throws Exception {
- fileInputStream.close();
- }
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation.container;
-
-import org.picocontainer.ComponentAdapter;
-import org.picocontainer.DefaultPicoContainer;
-import org.picocontainer.MutablePicoContainer;
-import org.picocontainer.behaviors.OptInCaching;
-import org.picocontainer.lifecycle.ReflectionLifecycleStrategy;
-import org.picocontainer.monitors.NullComponentMonitor;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.utils.log.Profiler;
-import org.sonar.core.platform.ComponentContainer;
-
-public class CEContainer extends ComponentContainer {
- public CEContainer(ComponentContainer parent) {
- super(createContainer(parent), parent);
- }
-
- private static MutablePicoContainer createContainer(ComponentContainer parent) {
- ReflectionLifecycleStrategy lifecycleStrategy = new ReflectionLifecycleStrategy(new NullComponentMonitor(), "start", "stop", "close") {
- @Override
- public boolean isLazy(ComponentAdapter<?> adapter) {
- return true;
- }
-
- @Override
- public void start(Object component) {
- Profiler profiler = Profiler.createIfTrace(Loggers.get(ComponentContainer.class));
- profiler.start();
- super.start(component);
- profiler.stopTrace(component.getClass().getCanonicalName() + " started");
- }
- };
-
- return new DefaultPicoContainer(new OptInCaching(), lifecycleStrategy, parent.getPicoContainer());
- }
-}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.container;
+
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.server.computation.ReportQueue.Item;
+import org.sonar.server.computation.step.ComputationStep;
+
+/**
+ * The Compute Engine container. Created for a specific parent {@link ComponentContainer} and a specific {@link Item}.
+ */
+public interface ComputeEngineContainer {
+ Item getItem();
+
+ ComponentContainer getParent();
+
+ /**
+ * Process the current {@link Item}
+ */
+ void process();
+
+ /**
+ * Clean's up resources after process has been called and has returned.
+ */
+ void cleanup();
+
+ /**
+ */
+ <T extends ComputationStep> T getStep(Class<T> type);
+
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.container;
+
+import java.util.Arrays;
+import java.util.List;
+import org.picocontainer.ComponentAdapter;
+import org.picocontainer.DefaultPicoContainer;
+import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.behaviors.OptInCaching;
+import org.picocontainer.lifecycle.ReflectionLifecycleStrategy;
+import org.picocontainer.monitors.NullComponentMonitor;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.api.utils.log.Profiler;
+import org.sonar.core.issue.db.UpdateConflictResolver;
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.server.computation.ComputationService;
+import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.activity.ActivityManager;
+import org.sonar.server.computation.batch.BatchReportReaderImpl;
+import org.sonar.server.computation.batch.ReportExtractor;
+import org.sonar.server.computation.component.DbComponentsRefCache;
+import org.sonar.server.computation.component.ProjectSettingsRepository;
+import org.sonar.server.computation.issue.IssueCache;
+import org.sonar.server.computation.issue.IssueComputation;
+import org.sonar.server.computation.issue.RuleCache;
+import org.sonar.server.computation.issue.RuleCacheLoader;
+import org.sonar.server.computation.issue.ScmAccountCache;
+import org.sonar.server.computation.issue.ScmAccountCacheLoader;
+import org.sonar.server.computation.issue.SourceLinesCache;
+import org.sonar.server.computation.language.PlatformLanguageRepository;
+import org.sonar.server.computation.measure.MetricCache;
+import org.sonar.server.computation.step.ComputationStep;
+import org.sonar.server.computation.step.ComputationSteps;
+import org.sonar.server.view.index.ViewIndex;
+
+import static java.util.Objects.requireNonNull;
+
+public class ComputeEngineContainerImpl extends ComponentContainer implements ComputeEngineContainer {
+ private final ReportQueue.Item item;
+ private final ComputationSteps steps;
+
+ public ComputeEngineContainerImpl(ComponentContainer parent, ReportQueue.Item item) {
+ super(createContainer(requireNonNull(parent)));
+
+ this.item = item;
+ this.steps = new ComputationSteps(this);
+
+ populateContainer(requireNonNull(item));
+ }
+
+ @Override
+ public ReportQueue.Item getItem() {
+ return item;
+ }
+
+ private void populateContainer(ReportQueue.Item item) {
+ add(item);
+ add(steps);
+ addSingletons(componentClasses());
+ addSingletons(steps.orderedStepClasses());
+ }
+
+ /**
+ * Creates a PicContainer which extends the specified ComponentContainer <strong>but is not referenced in return</strong>
+ * and lazily starts its components.
+ */
+ private static MutablePicoContainer createContainer(ComponentContainer parent) {
+ ReflectionLifecycleStrategy lifecycleStrategy = new ReflectionLifecycleStrategy(new NullComponentMonitor(), "start", "stop", "close") {
+ @Override
+ public boolean isLazy(ComponentAdapter<?> adapter) {
+ return true;
+ }
+
+ @Override
+ public void start(Object component) {
+ Profiler profiler = Profiler.createIfTrace(Loggers.get(ComponentContainer.class));
+ profiler.start();
+ super.start(component);
+ profiler.stopTrace(component.getClass().getCanonicalName() + " started");
+ }
+ };
+
+ return new DefaultPicoContainer(new OptInCaching(), lifecycleStrategy, parent.getPicoContainer());
+ }
+
+ /**
+ * List of all objects to be injected in the picocontainer dedicated to computation stack.
+ * Does not contain the steps declared in {@link org.sonar.server.computation.step.ComputationSteps#orderedStepClasses()}.
+ */
+ private static List componentClasses() {
+ return Arrays.asList(
+ ActivityManager.class,
+ ReportExtractor.class,
+ BatchReportReaderImpl.class,
+
+ // repositories
+ PlatformLanguageRepository.class,
+ ProjectSettingsRepository.class,
+
+ // component caches
+ DbComponentsRefCache.class,
+
+ // issues
+ ScmAccountCacheLoader.class,
+ ScmAccountCache.class,
+ SourceLinesCache.class,
+ IssueComputation.class,
+ RuleCache.class,
+ RuleCacheLoader.class,
+ IssueCache.class,
+ MetricCache.class,
+ UpdateConflictResolver.class,
+
+ // views
+ ViewIndex.class,
+
+ // ComputationService
+ ComputationService.class
+ );
+ }
+
+ public void process() {
+ // calls the first
+ getComponentByType(ComputationService.class).process();
+ }
+
+ public void cleanup() {
+ stopComponents();
+ }
+
+ @Override
+ public <T extends ComputationStep> T getStep(Class<T> type) {
+ return getComponentByType(type);
+ }
+
+ @Override
+ public String toString() {
+ return "ComputeEngineContainerImpl";
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.container;
+
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.server.computation.ReportQueue;
+
+/**
+ * Compute
+ */
+public interface ContainerFactory {
+
+ ComputeEngineContainer create(ComponentContainer parent, ReportQueue.Item item);
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.container;
+
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.server.computation.ReportQueue;
+
+public class ContainerFactoryImpl implements ContainerFactory {
+ @Override
+ public ComputeEngineContainer create(ComponentContainer parent, ReportQueue.Item item) {
+ return new ComputeEngineContainerImpl(parent, item);
+ }
+}
import com.google.common.collect.Iterables;
import java.util.Arrays;
import java.util.List;
-import org.sonar.server.computation.container.CEContainer;
+import org.sonar.server.computation.container.ComputeEngineContainer;
/**
* Ordered list of steps to be executed
* List of all {@link org.sonar.server.computation.step.ComputationStep},
* ordered by execution sequence.
*/
- public static List<Class<? extends ComputationStep>> orderedStepClasses() {
+ public List<Class<? extends ComputationStep>> orderedStepClasses() {
return Arrays.asList(
PopulateComponentsUuidAndKeyStep.class,
ValidateProjectStep.class,
SendIssueNotificationsStep.class);
}
- private final CEContainer ceContainer;
+ private final ComputeEngineContainer computeEngineContainer;
- public ComputationSteps(CEContainer ceContainer) {
- this.ceContainer = ceContainer;
+ public ComputationSteps(ComputeEngineContainer computeEngineContainer) {
+ this.computeEngineContainer = computeEngineContainer;
}
public Iterable<ComputationStep> instances() {
return Iterables.transform(orderedStepClasses(), new Function<Class<? extends ComputationStep>, ComputationStep>() {
@Override
public ComputationStep apply(Class<? extends ComputationStep> input) {
- ComputationStep computationStepType = ceContainer.getComponentByType(input);
+ ComputationStep computationStepType = computeEngineContainer.getStep(input);
if (computationStepType == null) {
throw new IllegalStateException(String.format("Component not found: %s", input));
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation;
-
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ComputationContainerTest {
-
- @Test
- public void componentClasses() {
- assertThat(ComputationContainer.componentClasses()).isNotEmpty();
- }
-}
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.computation.db.AnalysisReportDto.Status;
-import org.sonar.server.computation.activity.CEActivityManager;
+import org.sonar.server.computation.activity.ActivityManager;
import org.sonar.server.computation.batch.BatchReportReaderRule;
import org.sonar.server.computation.language.LanguageRepository;
import org.sonar.server.computation.step.ComputationStep;
ComputationStep projectStep1 = mockStep();
ComputationStep projectStep2 = mockStep();
ComputationSteps steps = mock(ComputationSteps.class);
- CEActivityManager activityManager = mock(CEActivityManager.class);
+ ActivityManager activityManager = mock(ActivityManager.class);
System2 system = mock(System2.class);
AnalysisReportDto dto = AnalysisReportDto.newForTests(1L).setProjectKey("P1").setUuid("U1").setStatus(Status.PENDING);
ComputationService sut;
package org.sonar.server.computation;
+import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.rules.Timeout;
import org.sonar.api.platform.Server;
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.server.computation.container.ContainerFactory;
-import java.util.concurrent.TimeUnit;
-
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
public class ComputationThreadLauncherTest {
ComputationThreadLauncher sut;
ReportQueue queue;
+ ComponentContainer componentContainer;
+ ContainerFactory containerFactory;
@Before
public void before() {
this.queue = mock(ReportQueue.class);
+ this.componentContainer = mock(ComponentContainer.class);
+ this.containerFactory = mock(ContainerFactory.class);
}
@After
@Test
public void call_findAndBook_when_launching_a_recurrent_task() throws Exception {
- sut = new ComputationThreadLauncher(queue, 0, 1, TimeUnit.MILLISECONDS);
+ sut = new ComputationThreadLauncher(queue, componentContainer, containerFactory, 0, 1, TimeUnit.MILLISECONDS);
sut.onServerStart(mock(Server.class));
@Test
public void call_findAndBook_when_executing_task_immediately() throws Exception {
- sut = new ComputationThreadLauncher(queue, 1, 1, TimeUnit.HOURS);
+ sut = new ComputationThreadLauncher(queue, componentContainer, containerFactory, 1, 1, TimeUnit.HOURS);
sut.start();
sut.startAnalysisTaskNow();
@Test
public void test_real_constructor() throws Exception {
- sut = new ComputationThreadLauncher(queue);
+ sut = new ComputationThreadLauncher(queue, componentContainer);
sut.start();
}
package org.sonar.server.computation;
+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.computation.db.AnalysisReportDto;
-
-import java.io.IOException;
+import org.sonar.core.platform.ComponentContainer;
+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.*;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
public class ComputationThreadTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
-
@Rule
public LogTester logTester = new LogTester();
- ComputationContainer container = mock(ComputationContainer.class);
ReportQueue queue = mock(ReportQueue.class);
- ComputationThread sut = new ComputationThread(queue, container);
+ ComponentContainer componentContainer = mock(ComponentContainer.class);
+ ContainerFactory containerFactory = mock(ContainerFactory.class);
+ ComputationThread sut = new ComputationThread(queue, componentContainer, containerFactory);
@Test
public void do_nothing_if_queue_empty() {
sut.run();
verify(queue).pop();
- verifyZeroInteractions(container);
+ verifyZeroInteractions(containerFactory);
}
@Test
public void pop_queue_and_integrate_report() throws IOException {
AnalysisReportDto report = AnalysisReportDto.newForTests(1L);
ReportQueue.Item item = new ReportQueue.Item(report, temp.newFile());
+
when(queue.pop()).thenReturn(item);
+ when(containerFactory.create(componentContainer, item)).thenReturn(mock(ComputeEngineContainer.class));
sut.run();
verify(queue).pop();
- verify(container).execute(item);
+ verify(containerFactory).create(componentContainer, item);
}
@Test
assertThat(logTester.logs()).contains("Failed to pop the queue of analysis reports");
}
- @Test
- public void handle_error_during_integration() throws Exception {
- AnalysisReportDto report = AnalysisReportDto.newForTests(1L).setProjectKey("P1");
- ReportQueue.Item item = new ReportQueue.Item(report, temp.newFile());
- when(queue.pop()).thenReturn(item);
- doThrow(new IllegalStateException("pb")).when(container).execute(item);
-
- sut.run();
-
- assertThat(logTester.logs()).contains("Failed to process analysis report 1 of project P1");
- }
-
@Test
public void handle_error_during_removal_from_queue() throws Exception {
+ when(containerFactory.create(any(ComponentContainer.class), any(ReportQueue.Item.class))).thenReturn(mock(ComputeEngineContainer.class));
+
AnalysisReportDto report = AnalysisReportDto.newForTests(1L).setProjectKey("P1");
ReportQueue.Item item = new ReportQueue.Item(report, temp.newFile());
when(queue.pop()).thenReturn(item);
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.activity;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.activity.Activity;
+import org.sonar.server.activity.ActivityService;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+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 {
+ @ClassRule
+ public static DbTester dbTester = new DbTester();
+
+ 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() throws Exception {
+ dbTester.truncateTables();
+ DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao());
+
+ underTest = new ActivityManager(activityService, dbClient);
+ }
+
+ @Test
+ public void process_existing_project() throws Exception {
+ 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() throws Exception {
+ 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");
+ }
+
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation.activity;
-
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.mockito.ArgumentCaptor;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.persistence.DbTester;
-import org.sonar.server.activity.Activity;
-import org.sonar.server.activity.ActivityService;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.db.DbClient;
-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 CEActivityManagerTest {
- @ClassRule
- public static DbTester dbTester = new DbTester();
-
- 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);
- CEActivityManager underTest;
-
- @Before
- public void setup() throws Exception {
- dbTester.truncateTables();
- DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao());
-
- underTest = new CEActivityManager(activityService, dbClient);
- }
-
- @Test
- public void process_existing_project() throws Exception {
- 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() throws Exception {
- 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");
- }
-
-}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.container;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import java.util.Set;
+import org.junit.Test;
+import org.picocontainer.ComponentAdapter;
+import org.reflections.Reflections;
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.step.ComputationStep;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class ComputeEngineContainerImplTest {
+ @Test(expected = NullPointerException.class)
+ public void constructor_fails_fast_on_null_container() {
+ new ComputeEngineContainerImpl(null, mock(ReportQueue.Item.class));
+ }
+ @Test(expected = NullPointerException.class)
+ public void constructor_fails_fast_on_null_item() {
+ new ComputeEngineContainerImpl(new ComponentContainer(), null);
+ }
+
+ @Test
+ public void ce_container_is_not_child_of_specified_container() {
+ ComponentContainer parent = new ComponentContainer();
+ ComputeEngineContainerImpl ceContainer = new ComputeEngineContainerImpl(parent, mock(ReportQueue.Item.class));
+
+ assertThat(parent.getChild()).isNull();
+ assertThat(parent.getPicoContainer().removeChildContainer(ceContainer.getPicoContainer())).isFalse();
+ }
+
+ @Test
+ public void all_steps_from_package_step_are_present_in_container() {
+ ComputeEngineContainerImpl ceContainer = new ComputeEngineContainerImpl(new ComponentContainer(), mock(ReportQueue.Item.class));
+
+ Set<String> stepsCanonicalNames = retrieveStepPackageStepsCanonicalNames();
+
+ Set<String> typesInContainer = Sets.newHashSet(
+ Iterables.transform(
+ Iterables.filter(
+ Iterables.transform(
+ ceContainer.getPicoContainer().getComponentAdapters(),
+ ComponentAdapterToImplementationClass.INSTANCE),
+ IsComputationStep.INSTANCE),
+ ClassToCanonicalName.INSTANCE));
+
+ assertThat(typesInContainer).isEqualTo(stepsCanonicalNames);
+ }
+
+ /**
+ * Compute set of canonical names of classes implementing ComputationStep in package step using reflection.
+ */
+ private Set<String> retrieveStepPackageStepsCanonicalNames() {
+ Reflections reflections = new Reflections("org.sonar.server.computation.step");
+
+ return Sets.newHashSet(Iterables.transform(reflections.getSubTypesOf(ComputationStep.class), ClassToCanonicalName.INSTANCE));
+ }
+
+ private enum ClassToCanonicalName implements Function<Class<?>, String> {
+ INSTANCE;
+
+ @Override
+ public String apply(Class<?> input) {
+ return input.getCanonicalName();
+ }
+ }
+
+ private enum ComponentAdapterToImplementationClass implements Function<ComponentAdapter<?>, Class<?>> {
+ INSTANCE;
+
+ @Override
+ public Class<?> apply(ComponentAdapter<?> input) {
+ return input.getComponentImplementation();
+ }
+ }
+
+ private enum IsComputationStep implements Predicate<Class<?>> {
+ INSTANCE;
+
+ @Override
+ public boolean apply(Class<?> input) {
+ return ComputationStep.class.isAssignableFrom(input);
+ }
+ }
+}
package org.sonar.server.computation.step;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
-import java.util.List;
+import com.google.common.collect.Sets;
+import java.util.Set;
import org.junit.Test;
+import org.picocontainer.ComponentAdapter;
+import org.reflections.Reflections;
import org.sonar.core.platform.ComponentContainer;
-import org.sonar.server.computation.container.CEContainer;
+import org.sonar.server.computation.ReportQueue;
+import org.sonar.server.computation.container.ComputeEngineContainerImpl;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
public class ComputationStepsTest {
- @Test
- public void ordered_steps() {
- CEContainer ceContainer = new CEContainer(new ComponentContainer());
- ceContainer.add(
- // unordered
- mock(ApplyPermissionsStep.class),
- mock(ParseReportStep.class),
- mock(IndexSourceLinesStep.class),
- mock(PersistIssuesStep.class),
- mock(IndexIssuesStep.class),
- mock(SwitchSnapshotStep.class),
- mock(PurgeDatastoresStep.class),
- mock(SendIssueNotificationsStep.class),
- mock(IndexComponentsStep.class),
- mock(PersistProjectLinksStep.class),
- mock(PersistMeasuresStep.class),
- mock(PersistEventsStep.class),
- mock(PersistDuplicationsStep.class),
- mock(PersistNumberOfDaysSinceLastCommitStep.class),
- mock(PersistFileSourcesStep.class),
- mock(PersistTestsStep.class),
- mock(IndexTestsStep.class),
- mock(PopulateComponentsUuidAndKeyStep.class),
- mock(PersistComponentsStep.class),
- mock(QualityProfileEventsStep.class),
- mock(ValidateProjectStep.class)
- );
- ComputationSteps computationSteps = new ComputationSteps(ceContainer);
-
- List<ComputationStep> steps = Lists.newArrayList(computationSteps.instances());
- assertThat(steps).hasSize(21);
- assertThat(steps.get(0)).isInstanceOf(PopulateComponentsUuidAndKeyStep.class);
- assertThat(steps.get(20)).isInstanceOf(SendIssueNotificationsStep.class);
- }
-
@Test
public void fail_if_a_step_is_not_registered_in_picocontainer() {
try {
- Lists.newArrayList(new ComputationSteps(new CEContainer(new ComponentContainer())).instances());
+ Lists.newArrayList(new ComputationSteps(mock(ComputeEngineContainerImpl.class)).instances());
fail();
} catch (IllegalStateException e) {
assertThat(e).hasMessageContaining("Component not found");
}
}
+
+ @Test
+ public void all_steps_from_package_step_are_present_in_container() {
+ ComputeEngineContainerImpl ceContainer = new ComputeEngineContainerImpl(new ComponentContainer(), mock(ReportQueue.Item.class));
+
+ Set<String> stepsCanonicalNames = retrieveStepPackageStepsCanonicalNames();
+
+ Set<String> typesInContainer = Sets.newHashSet(
+ Iterables.transform(
+ Iterables.filter(
+ Iterables.transform(
+ ceContainer.getPicoContainer().getComponentAdapters(),
+ ComponentAdapterToImplementationClass.INSTANCE),
+ IsComputationStep.INSTANCE),
+ ClassToCanonicalName.INSTANCE));
+
+ assertThat(typesInContainer).isEqualTo(stepsCanonicalNames);
+ }
+
+ /**
+ * Compute set of canonical names of classes implementing ComputationStep in package step using reflection.
+ */
+ private Set<String> retrieveStepPackageStepsCanonicalNames() {
+ Reflections reflections = new Reflections("org.sonar.server.computation.step");
+
+ return Sets.newHashSet(Iterables.transform(reflections.getSubTypesOf(ComputationStep.class), ClassToCanonicalName.INSTANCE));
+ }
+
+ private enum ClassToCanonicalName implements Function<Class<?>, String> {
+ INSTANCE;
+
+ @Override
+ public String apply(Class<?> input) {
+ return input.getCanonicalName();
+ }
+ }
+
+ private enum ComponentAdapterToImplementationClass implements Function<ComponentAdapter<?>, Class<?>> {
+ INSTANCE;
+
+ @Override
+ public Class<?> apply(ComponentAdapter<?> input) {
+ return input.getComponentImplementation();
+ }
+ }
+
+ private enum IsComputationStep implements Predicate<Class<?>> {
+ INSTANCE;
+
+ @Override
+ public boolean apply(Class<?> input) {
+ return ComputationStep.class.isAssignableFrom(input);
+ }
+ }
}
--- /dev/null
+<dataset>
+ <projects id="10" kee="P1" qualifier="TRK" uuid="ABCD" name="Project 1"/>
+ <snapshots
+ id="110" project_id="10" parent_snapshot_id="[null]" root_project_id="10" root_snapshot_id="[null]"
+ purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]"
+ period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]"
+ period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="[false]" depth="0"/>
+</dataset>
+++ /dev/null
-<dataset>
- <projects id="10" kee="P1" qualifier="TRK" uuid="ABCD" name="Project 1"/>
- <snapshots
- id="110" project_id="10" parent_snapshot_id="[null]" root_project_id="10" root_snapshot_id="[null]"
- purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]"
- period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]"
- period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
- status="P" islast="[false]" depth="0"/>
-</dataset>
* Create root container
*/
public ComponentContainer() {
+ this(createPicoContainer());
+ }
+
+ protected ComponentContainer(MutablePicoContainer picoContainer) {
this.parent = null;
this.child = null;
- this.pico = createPicoContainer();
+ this.pico = picoContainer;
this.componentKeys = new ComponentKeys();
propertyDefinitions = new PropertyDefinitions();
addSingleton(propertyDefinitions);
* Create child container
*/
protected ComponentContainer(ComponentContainer parent) {
- this(parent.pico.makeChildContainer(), parent);
- }
-
- /**
- * Create child container
- */
- protected ComponentContainer(MutablePicoContainer picoContainer, ComponentContainer parent) {
this.parent = parent;
- this.pico = picoContainer;
+ this.pico = parent.pico.makeChildContainer();
this.parent.child = this;
this.propertyDefinitions = parent.propertyDefinitions;
this.componentKeys = new ComponentKeys();
return this;
}
- public <T> T getComponentByType(Class<T> tClass) {
- return pico.getComponent(tClass);
+ public <T> T getComponentByType(Class<T> type) {
+ return pico.getComponent(type);
}
public Object getComponentByKey(Object key) {