}
dependency 'org.mybatis:mybatis:3.5.9'
dependency 'org.nanohttpd:nanohttpd:2.3.1'
- dependency 'org.picocontainer:picocontainer:2.15'
dependencySet(group: 'org.slf4j', version: '1.7.30') {
entry 'jcl-over-slf4j'
entry 'jul-to-slf4j'
import java.util.function.Function;
import java.util.function.UnaryOperator;
import javax.annotation.Nullable;
+import javax.inject.Inject;
import okhttp3.Credentials;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
private final String bitbucketCloudEndpoint;
private final String accessTokenEndpoint;
+ @Inject
public BitbucketCloudRestClient(OkHttpClient okHttpClient) {
this(okHttpClient, ENDPOINT, ACCESS_TOKEN_ENDPOINT);
}
package org.sonar.auth.bitbucket;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class BitbucketModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new BitbucketModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 9);
+ assertThat(container.getAddedObjects()).hasSize(9);
}
}
package org.sonar.auth.github;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class GitHubModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new GitHubModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 13);
+ assertThat(container.getAddedObjects()).hasSize(13);
}
}
*/
package org.sonar.auth.gitlab;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.Container;
+import static java.util.Collections.unmodifiableList;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class GitLabModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new GitLabModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 10);
+ assertThat(container.getAddedObjects()).hasSize(10);
}
+ private static class ListContainer implements Container {
+ private final List<Object> objects = new ArrayList<>();
+
+ @Override
+ public Container add(Object... objects) {
+ this.objects.add(objects);
+ return this;
+ }
+
+ public List<Object> getAddedObjects() {
+ return unmodifiableList(new ArrayList<>(objects));
+ }
+
+ @Override
+ public <T> T getComponentByType(Class<T> type) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T> Optional<T> getOptionalComponentByType(Class<T> type) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T> List<T> getComponentsByType(Class<T> type) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Container getParent() {
+ throw new UnsupportedOperationException();
+ }
+ }
}
package org.sonar.auth.ldap;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class LdapModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new LdapModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 3);
+ assertThat(container.getAddedObjects()).hasSize(3);
}
}
package org.sonar.auth.saml;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class SamlModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new SamlModule().configure(container);
- assertThat(container.size()).isGreaterThan(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER);
+ assertThat(container.getAddedObjects()).hasSize(13);
}
}
import org.sonar.api.server.ServerSide;
/**
- * When an implementation of this interface is available in Pico, the Compute Engine will use the value returned by
+ * When an implementation of this interface is available in the ioc container, the Compute Engine will use the value returned by
* {@link #get()} as the number of worker the Compute Engine should run on.
*/
@ComputeEngineSide
compile 'com.google.protobuf:protobuf-java'
compile 'com.googlecode.java-diff-utils:diffutils'
compile 'org.mybatis:mybatis'
- compile 'org.picocontainer:picocontainer'
compile project(':sonar-core')
compile project(':server:sonar-ce-common')
private final PostProjectAnalysisTask[] postProjectAnalysisTasks;
private final BatchReportReader reportReader;
- /**
- * Constructor used by Pico when there is no {@link PostProjectAnalysisTask} in the container.
- */
- public PostProjectAnalysisTasksExecutor(org.sonar.ce.task.CeTask ceTask, AnalysisMetadataHolder analysisMetadataHolder,
- QualityGateHolder qualityGateHolder, QualityGateStatusHolder qualityGateStatusHolder, BatchReportReader reportReader) {
- this(ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader, null);
- }
-
public PostProjectAnalysisTasksExecutor(org.sonar.ce.task.CeTask ceTask, AnalysisMetadataHolder analysisMetadataHolder, QualityGateHolder qualityGateHolder,
QualityGateStatusHolder qualityGateStatusHolder, BatchReportReader reportReader, @Nullable PostProjectAnalysisTask[] postProjectAnalysisTasks) {
this.analysisMetadataHolder = analysisMetadataHolder;
*/
package org.sonar.ce.task.projectanalysis.component;
-import javax.annotation.Nullable;
import org.sonar.api.utils.MessageException;
import org.sonar.ce.task.projectanalysis.analysis.MutableAnalysisMetadataHolder;
import org.sonar.scanner.protocol.output.ScannerReport;
-
import static org.sonar.scanner.protocol.output.ScannerReport.Metadata.BranchType.UNSET;
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+
public class BranchLoader {
private final MutableAnalysisMetadataHolder metadataHolder;
private final BranchLoaderDelegate delegate;
this(metadataHolder, null);
}
+ @Inject
public BranchLoader(MutableAnalysisMetadataHolder metadataHolder, @Nullable BranchLoaderDelegate delegate) {
this.metadataHolder = metadataHolder;
this.delegate = delegate;
import javax.annotation.Nullable;
import org.sonar.ce.task.CeTask;
import org.sonar.ce.task.container.TaskContainer;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
public interface ContainerFactory {
- TaskContainer create(ComponentContainer parent, CeTask task, @Nullable ReportAnalysisComponentProvider[] componentProviders);
+ TaskContainer create(SpringComponentContainer parent, CeTask task, @Nullable ReportAnalysisComponentProvider[] componentProviders);
}
import org.sonar.ce.task.CeTask;
import org.sonar.ce.task.container.TaskContainer;
import org.sonar.ce.task.container.TaskContainerImpl;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
public class ContainerFactoryImpl implements ContainerFactory {
@Override
- public TaskContainer create(ComponentContainer parent, CeTask task, @Nullable ReportAnalysisComponentProvider[] componentProviders) {
+ public TaskContainer create(SpringComponentContainer parent, CeTask task, @Nullable ReportAnalysisComponentProvider[] componentProviders) {
return new TaskContainerImpl(parent, new ProjectAnalysisTaskContainerPopulator(task, componentProviders));
}
}
container.add(SettingsLoader.class);
container.add(task);
container.add(steps);
- container.addSingletons(componentClasses());
+ container.add(componentClasses());
for (ReportAnalysisComponentProvider componentProvider : componentProviders) {
- container.addSingletons(componentProvider.getComponents());
+ container.add(componentProvider.getComponents());
}
- container.addSingletons(steps.orderedStepClasses());
+ container.add(steps.orderedStepClasses());
}
/**
- * List of all objects to be injected in the picocontainer dedicated to computation stack.
+ * List of all objects to be injected in the ioc container dedicated to computation stack.
* Does not contain the steps declared in {@link ReportComputationSteps#orderedStepClasses()}.
*/
private static List<Object> componentClasses() {
new ComputationTempFolderProvider(),
ReportModulesPath.class,
- MetricModule.class,
+ new MetricModule(),
// holders
AnalysisMetadataHolderImpl.class,
package org.sonar.ce.task.projectanalysis.duplication;
import javax.annotation.CheckForNull;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+import javax.inject.Inject;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.component.PathAwareCrawler;
import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
protected final MeasureRepository measureRepository;
private final DuplicationRepository duplicationRepository;
+ @Inject
public DuplicationMeasures(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository,
@Nullable DuplicationRepository duplicationRepository) {
this.treeRootHolder = treeRootHolder;
this.formulas = List.of(new DuplicationFormula());
}
- /**
- * Constructor used by Pico in Views where no DuplicationRepository is available.
- */
public DuplicationMeasures(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository) {
this(treeRootHolder, metricRepository, measureRepository, null);
}
import java.io.File;
import java.io.IOException;
-import javax.annotation.CheckForNull;
import org.apache.commons.io.FileUtils;
-import org.picocontainer.ComponentLifecycle;
-import org.picocontainer.PicoContainer;
-import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.impl.utils.DefaultTempFolder;
import org.sonar.api.utils.TempFolder;
import org.sonar.server.platform.ServerFileSystem;
+import org.springframework.context.annotation.Bean;
/**
* Provides a TempFolder instance pointing to a directory dedicated to the processing of a specific item.
* This directory will be deleted at the end of the processing.
* This directory is located in the "ce" directory of the temp directory of the SonarQube instance.
*/
-public class ComputationTempFolderProvider extends ProviderAdapter implements ComponentLifecycle<TempFolder> {
- private boolean started = false;
- @CheckForNull
- private DefaultTempFolder tempFolder = null;
-
+public class ComputationTempFolderProvider {
+ @Bean("ComputationTempFolder")
public TempFolder provide(ServerFileSystem fs) {
- if (this.tempFolder == null) {
- File tempDir = new File(fs.getTempDir(), "ce");
- try {
- FileUtils.forceMkdir(tempDir);
- } catch (IOException e) {
- throw new IllegalStateException("Unable to create computation temp directory " + tempDir, e);
- }
- File computationDir = new DefaultTempFolder(tempDir).newDir();
- this.tempFolder = new DefaultTempFolder(computationDir, true);
+ File tempDir = new File(fs.getTempDir(), "ce");
+ try {
+ FileUtils.forceMkdir(tempDir);
+ } catch (IOException e) {
+ throw new IllegalStateException("Unable to create computation temp directory " + tempDir, e);
}
- return this.tempFolder;
- }
-
- @Override
- public void start(PicoContainer container) {
- this.started = true;
+ File computationDir = new DefaultTempFolder(tempDir).newDir();
+ return new DefaultTempFolder(computationDir, true);
}
-
- @Override
- public void stop(PicoContainer container) {
- if (tempFolder != null) {
- tempFolder.stop();
- }
- }
-
- @Override
- public void dispose(PicoContainer container) {
- // nothing to do
- }
-
- @Override
- public boolean componentHasLifecycle() {
- return true;
- }
-
- @Override
- public boolean isStarted() {
- return started;
- }
-
}
import com.google.common.base.Preconditions;
import java.util.Date;
import java.util.Optional;
+import javax.inject.Inject;
import org.sonar.api.issue.Issue;
import org.sonar.api.rules.RuleType;
import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
private final DebtCalculator debtCalculator;
private final AnalysisMetadataHolder analysisMetadataHolder;
+ @Inject
public IssueLifecycle(AnalysisMetadataHolder analysisMetadataHolder, IssueWorkflow workflow, IssueFieldsSetter updater, DebtCalculator debtCalculator,
RuleRepository ruleRepository) {
this(analysisMetadataHolder, IssueChangeContext.createScan(new Date(analysisMetadataHolder.getAnalysisDate())), workflow, updater, debtCalculator, ruleRepository);
*/
package org.sonar.ce.task.projectanalysis.issue;
-import java.io.File;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.TempFolder;
import org.sonar.ce.task.projectanalysis.util.cache.ProtobufIssueDiskCache;
+import javax.inject.Inject;
+import java.io.File;
+
/**
* Cache of all the issues involved in the analysis. Their state is as it will be
* persisted in database (after issue tracking, auto-assignment, ...)
*/
public class ProtoIssueCache extends ProtobufIssueDiskCache {
-
- // this constructor is used by picocontainer
+ @Inject
public ProtoIssueCache(TempFolder tempFolder, System2 system2) {
super(tempFolder.newFile("issues", ".dat"), system2);
}
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.tracking.SimpleTracker;
import org.sonar.core.issue.tracking.Tracking;
+import org.springframework.beans.factory.annotation.Autowired;
public class SiblingsIssueMerger {
private final SiblingsIssuesLoader siblingsIssuesLoader;
private final SimpleTracker<DefaultIssue, SiblingIssue> tracker;
private final IssueLifecycle issueLifecycle;
+ @Autowired(required = false)
public SiblingsIssueMerger(SiblingsIssuesLoader resolvedSiblingsIssuesLoader, IssueLifecycle issueLifecycle) {
this(resolvedSiblingsIssuesLoader, new SimpleTracker<>(), issueLifecycle);
}
+ @Autowired(required = false)
public SiblingsIssueMerger(SiblingsIssuesLoader siblingsIssuesLoader, SimpleTracker<DefaultIssue, SiblingIssue> tracker, IssueLifecycle issueLifecycle) {
this.siblingsIssuesLoader = siblingsIssuesLoader;
this.tracker = tracker;
import java.util.Optional;
import javax.annotation.Nonnull;
import org.sonar.api.resources.Language;
+import org.springframework.beans.factory.annotation.Autowired;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.collect.Iterables.filter;
private final Map<String, Language> languagesByKey;
+ @Autowired(required = false)
public LanguageRepositoryImpl() {
this.languagesByKey = Collections.emptyMap();
}
+ @Autowired(required = false)
public LanguageRepositoryImpl(Language... languages) {
this.languagesByKey = uniqueIndex(filter(asList(languages), notNull()), LanguageToKey.INSTANCE);
}
import org.sonar.ce.task.projectanalysis.metric.Metric;
import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
import org.sonar.ce.task.step.ComputationStep;
+import org.springframework.beans.factory.annotation.Autowired;
/**
* Execute {@link PostMeasuresComputationCheck} instances in no specific order.
private final AnalysisMetadataHolder analysisMetadataHolder;
private final PostMeasuresComputationCheck[] extensions;
+ @Autowired(required = false)
public PostMeasuresComputationChecksStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository,
AnalysisMetadataHolder analysisMetadataHolder, PostMeasuresComputationCheck[] extensions) {
this.treeRootHolder = treeRootHolder;
/**
* Used when zero {@link PostMeasuresComputationCheck} are registered into container.
*/
+ @Autowired(required = false)
public PostMeasuresComputationChecksStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository,
AnalysisMetadataHolder analysisMetadataHolder) {
this(treeRootHolder, metricRepository, measureRepository, analysisMetadataHolder, new PostMeasuresComputationCheck[0]);
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.metric.MetricDto;
@Override
public Iterable<ComputationStep> instances() {
- return Iterables.transform(
- orderedStepClasses(),
- input -> {
- ComputationStep computationStepType = container.getComponentByType(input);
- if (computationStepType == null) {
- throw new IllegalStateException(String.format("Component not found: %s", input));
- }
- return computationStepType;
- });
+ return Iterables.transform(orderedStepClasses(), container::getComponentByType);
}
}
package org.sonar.ce.task.projectanalysis.step;
import java.util.List;
+import javax.annotation.Nullable;
+import javax.inject.Inject;
import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
import org.sonar.ce.task.projectanalysis.component.Component;
import org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit;
/**
* Constructor used when processing a Report (ie. a {@link BatchReportReader} instance is available in the container)
*/
- public CoverageMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository, BatchReportReader reportReader) {
+ @Inject
+ public CoverageMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository, @Nullable BatchReportReader reportReader) {
this.treeRootHolder = treeRootHolder;
this.metricRepository = metricRepository;
this.measureRepository = measureRepository;
this.uncoveredConditionsMetric = metricRepository.getByKey(UNCOVERED_CONDITIONS_KEY);
}
- /**
- * Constructor used when processing Views (ie. no {@link BatchReportReader} instance is available in the container)
- */
- public CoverageMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository) {
- this.treeRootHolder = treeRootHolder;
- this.metricRepository = metricRepository;
- this.measureRepository = measureRepository;
- this.linesToCoverMetric = metricRepository.getByKey(LINES_TO_COVER_KEY);
- this.uncoveredLinesMetric = metricRepository.getByKey(UNCOVERED_LINES_KEY);
- this.conditionsToCoverMetric = metricRepository.getByKey(CONDITIONS_TO_COVER_KEY);
- this.uncoveredConditionsMetric = metricRepository.getByKey(UNCOVERED_CONDITIONS_KEY);
- this.reportReader = null;
- }
-
@Override
public void execute(ComputationStep.Context context) {
if (reportReader != null) {
}
new PathAwareCrawler<>(
FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository).buildFor(COVERAGE_FORMULAS))
- .visit(treeRootHolder.getReportTreeRoot());
+ .visit(treeRootHolder.getReportTreeRoot());
}
private class FileCoverageVisitor extends TypeAwareVisitorAdapter {
import org.sonar.ce.task.projectanalysis.api.measurecomputer.MeasureComputerWrapper;
import org.sonar.ce.task.projectanalysis.measure.MutableMeasureComputersHolder;
import org.sonar.ce.task.step.ComputationStep;
+import org.springframework.beans.factory.annotation.Autowired;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.FluentIterable.from;
private final MutableMeasureComputersHolder measureComputersHolder;
private final MeasureComputer[] measureComputers;
+ @Autowired(required = false)
public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder, Metrics[] metricsRepositories, MeasureComputer[] measureComputers) {
this.measureComputersHolder = measureComputersHolder;
this.measureComputers = measureComputers;
}
/**
- * Constructor override used by Pico to instantiate the class when no plugin is defining metrics
+ * Constructor override used by the ioc container to instantiate the class when no plugin is defining metrics
*/
+ @Autowired(required = false)
public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder, MeasureComputer[] measureComputers) {
this(measureComputersHolder, new Metrics[] {}, measureComputers);
}
/**
- * Constructor override used by Pico to instantiate the class when no plugin is defining measure computers
+ * Constructor override used by the ioc container to instantiate the class when no plugin is defining measure computers
*/
+ @Autowired(required = false)
public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder, Metrics[] metricsRepositories) {
this(measureComputersHolder, metricsRepositories, new MeasureComputer[] {});
}
/**
- * Constructor override used by Pico to instantiate the class when no plugin is defining metrics neither measure computers
+ * Constructor override used by the ioc container to instantiate the class when no plugin is defining metrics neither measure computers
*/
+ @Autowired(required = false)
public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder) {
this(measureComputersHolder, new Metrics[] {}, new MeasureComputer[] {});
}
import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.ce.task.projectanalysis.view.TriggerViewRefreshDelegate;
import org.sonar.ce.task.step.ComputationStep;
+import org.springframework.beans.factory.annotation.Autowired;
/**
* This step will trigger refresh of Portfolios and Applications that include the current project.
private final AnalysisMetadataHolder analysisMetadata;
/**
- * Constructor used by Pico when no implementation of {@link TriggerViewRefreshDelegate} is available
+ * Constructor used by the ioc container when no implementation of {@link TriggerViewRefreshDelegate} is available
*/
+ @Autowired(required = false)
public TriggerViewRefreshStep(AnalysisMetadataHolder analysisMetadata) {
this.analysisMetadata = analysisMetadata;
this.triggerViewRefreshDelegates = new TriggerViewRefreshDelegate[0];
}
/**
- * Constructor used by Pico when an implementation of {@link TriggerViewRefreshDelegate} is available
+ * Constructor used by the ioc container when an implementation of {@link TriggerViewRefreshDelegate} is available
*/
+ @Autowired(required = false)
public TriggerViewRefreshStep(AnalysisMetadataHolder analysisMetadata, TriggerViewRefreshDelegate[] triggerViewRefreshDelegates) {
this.analysisMetadata = analysisMetadata;
this.triggerViewRefreshDelegates = triggerViewRefreshDelegates;
import org.sonar.ce.task.step.ComputationStep;
import org.sonar.ce.task.step.ComputationStepExecutor;
import org.sonar.ce.task.taskprocessor.CeTaskProcessor;
-import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.Container;
import org.sonar.core.platform.ContainerPopulator;
+import org.sonar.core.platform.SpringComponentContainer;
import static org.sonar.db.ce.CeTaskTypes.AUDIT_PURGE;
public class AuditPurgeTaskProcessor implements CeTaskProcessor {
private static final Set<String> HANDLED_TYPES = Set.of(AUDIT_PURGE);
- private final ComponentContainer ceEngineContainer;
+ private final SpringComponentContainer ceEngineContainer;
- public AuditPurgeTaskProcessor(ComponentContainer ceEngineContainer) {
+ public AuditPurgeTaskProcessor(SpringComponentContainer ceEngineContainer) {
this.ceEngineContainer = ceEngineContainer;
}
import org.sonar.ce.task.step.ComputationStep;
import org.sonar.ce.task.step.ComputationStepExecutor;
import org.sonar.ce.task.taskprocessor.CeTaskProcessor;
-import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.Container;
import org.sonar.core.platform.ContainerPopulator;
+import org.sonar.core.platform.SpringComponentContainer;
import static org.sonar.db.ce.CeTaskTypes.BRANCH_ISSUE_SYNC;
public class IssueSyncTaskProcessor implements CeTaskProcessor {
private static final Set<String> HANDLED_TYPES = ImmutableSet.of(BRANCH_ISSUE_SYNC);
- private final ComponentContainer ceEngineContainer;
+ private final SpringComponentContainer ceEngineContainer;
- public IssueSyncTaskProcessor(ComponentContainer ceEngineContainer) {
+ public IssueSyncTaskProcessor(SpringComponentContainer ceEngineContainer) {
this.ceEngineContainer = ceEngineContainer;
}
import java.util.Collections;
import java.util.Set;
import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.ce.task.CeTask;
import org.sonar.ce.task.CeTaskResult;
import org.sonar.ce.task.container.TaskContainer;
import org.sonar.ce.task.step.ComputationStepExecutor;
import org.sonar.ce.task.taskprocessor.CeTaskProcessor;
import org.sonar.ce.task.taskprocessor.TaskResultHolder;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.db.ce.CeTaskTypes;
import org.sonar.ce.task.projectanalysis.container.ReportAnalysisComponentProvider;
+import org.springframework.beans.factory.annotation.Autowired;
public class ReportTaskProcessor implements CeTaskProcessor {
private static final Set<String> HANDLED_TYPES = Collections.singleton(CeTaskTypes.REPORT);
private final ContainerFactory containerFactory;
- private final ComponentContainer serverContainer;
+ private final SpringComponentContainer serverContainer;
@CheckForNull
private final ReportAnalysisComponentProvider[] componentProviders;
- /**
- * Used when at least one Privileged plugin is installed
- */
- public ReportTaskProcessor(ContainerFactory containerFactory, ComponentContainer serverContainer, ReportAnalysisComponentProvider[] componentProviders) {
+ @Autowired(required = false)
+ public ReportTaskProcessor(ContainerFactory containerFactory, SpringComponentContainer serverContainer, @Nullable ReportAnalysisComponentProvider[] componentProviders) {
this.containerFactory = containerFactory;
this.serverContainer = serverContainer;
this.componentProviders = componentProviders;
}
- /**
- * Used when no privileged plugin is installed
- */
- public ReportTaskProcessor(ContainerFactory containerFactory, ComponentContainer serverContainer) {
- this.containerFactory = containerFactory;
- this.serverContainer = serverContainer;
- this.componentProviders = null;
- }
-
/**
* Used when loaded in WebServer where none of the dependencies are available and where only
* {@link #getHandledCeTaskTypes()} will be called.
*/
+ @Autowired(required = false)
public ReportTaskProcessor() {
- this(null, null, null);
+ this.containerFactory = null;
+ this.serverContainer = null;
+ this.componentProviders = null;
}
@Override
container.add(projectDescriptor);
container.add(steps);
- container.addSingletons(COMPONENT_CLASSES);
- container.addSingletons(steps.orderedStepClasses());
+ container.add(COMPONENT_CLASSES);
+ container.add(steps.orderedStepClasses());
}
}
import org.sonar.ce.task.projectexport.ProjectExportContainerPopulator;
import org.sonar.ce.task.projectexport.ProjectExportProcessor;
import org.sonar.ce.task.taskprocessor.CeTaskProcessor;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import static org.sonar.db.ce.CeTaskTypes.PROJECT_EXPORT;
public class ProjectExportTaskProcessor implements CeTaskProcessor {
- private final ComponentContainer componentContainer;
+ private final SpringComponentContainer componentContainer;
- public ProjectExportTaskProcessor(ComponentContainer componentContainer) {
+ public ProjectExportTaskProcessor(SpringComponentContainer componentContainer) {
this.componentContainer = componentContainer;
}
package org.sonar.ce.task.projectexport.util;
import java.io.File;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.config.Configuration;
import org.sonar.api.server.ServerSide;
package org.sonar.ce.task.projectexport.util;
import java.io.File;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.config.Configuration;
import org.sonar.api.server.ServerSide;
@Test
@UseDataProvider("booleanValues")
public void does_not_fail_when_there_is_no_PostProjectAnalysisTasksExecutor(boolean allStepsExecuted) {
- new PostProjectAnalysisTasksExecutor(ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader)
+ new PostProjectAnalysisTasksExecutor(ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, reportReader, null)
.finished(allStepsExecuted);
}
import com.google.common.collect.ImmutableList;
import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
-import org.picocontainer.DefaultPicoContainer;
-import org.picocontainer.PicoContainer;
import org.reflections.Reflections;
import org.sonar.ce.task.CeTask;
-import org.sonar.ce.task.container.TaskContainer;
import org.sonar.ce.task.projectanalysis.step.PersistComponentsStep;
+import org.sonar.ce.task.projectanalysis.task.ListTaskContainer;
import org.sonar.ce.task.step.ComputationStep;
-import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.util.stream.MoreCollectors;
import static com.google.common.collect.Sets.difference;
public class ProjectAnalysisTaskContainerPopulatorTest {
private static final String PROJECTANALYSIS_STEP_PACKAGE = "org.sonar.ce.task.projectanalysis.step";
- private CeTask task = mock(CeTask.class);
- private ProjectAnalysisTaskContainerPopulator underTest;
+ private final CeTask task = mock(CeTask.class);
+ private final ProjectAnalysisTaskContainerPopulator underTest = new ProjectAnalysisTaskContainerPopulator(task, null);
@Test
public void item_is_added_to_the_container() {
- underTest = new ProjectAnalysisTaskContainerPopulator(task, null);
- AddedObjectsRecorderTaskContainer container = new AddedObjectsRecorderTaskContainer();
+ ListTaskContainer container = new ListTaskContainer();
underTest.populateContainer(container);
- assertThat(container.added).contains(task);
+ assertThat(container.getAddedComponents()).contains(task);
}
@Test
public void all_computation_steps_are_added_in_order_to_the_container() {
- underTest = new ProjectAnalysisTaskContainerPopulator(task, null);
- AddedObjectsRecorderTaskContainer container = new AddedObjectsRecorderTaskContainer();
+ ListTaskContainer container = new ListTaskContainer();
underTest.populateContainer(container);
- Set<String> computationStepClassNames = container.added.stream()
+ Set<String> computationStepClassNames = container.getAddedComponents().stream()
.map(s -> {
if (s instanceof Class) {
return (Class<?>) s;
@Test
public void at_least_one_core_step_is_added_to_the_container() {
- underTest = new ProjectAnalysisTaskContainerPopulator(task, null);
- AddedObjectsRecorderTaskContainer container = new AddedObjectsRecorderTaskContainer();
+ ListTaskContainer container = new ListTaskContainer();
underTest.populateContainer(container);
- assertThat(container.added).contains(PersistComponentsStep.class);
+ assertThat(container.getAddedComponents()).contains(PersistComponentsStep.class);
}
@Test
ReportAnalysisComponentProvider componentProvider = mock(ReportAnalysisComponentProvider.class);
when(componentProvider.getComponents()).thenReturn(ImmutableList.of(object, clazz));
- underTest = new ProjectAnalysisTaskContainerPopulator(task, new ReportAnalysisComponentProvider[] {componentProvider});
- AddedObjectsRecorderTaskContainer container = new AddedObjectsRecorderTaskContainer();
+ ProjectAnalysisTaskContainerPopulator populator = new ProjectAnalysisTaskContainerPopulator(task, new ReportAnalysisComponentProvider[] {componentProvider});
+ ListTaskContainer container = new ListTaskContainer();
container.add(componentProvider);
- underTest.populateContainer(container);
+ populator.populateContainer(container);
- assertThat(container.added).contains(object, clazz);
+ assertThat(container.getAddedComponents()).contains(object, clazz);
}
private static final class MyClass {
}
- private static class AddedObjectsRecorderTaskContainer implements TaskContainer {
- private static final DefaultPicoContainer SOME_EMPTY_PICO_CONTAINER = new DefaultPicoContainer();
-
- private List<Object> added = new ArrayList<>();
-
- @Override
- public void bootup() {
- // no effect
- }
-
- @Override
- public ComponentContainer getParent() {
- throw new UnsupportedOperationException("getParent is not implemented");
- }
-
- @Override
- public void close() {
- throw new UnsupportedOperationException("cleanup is not implemented");
- }
-
- @Override
- public PicoContainer getPicoContainer() {
- return SOME_EMPTY_PICO_CONTAINER;
- }
-
- @Override
- public ComponentContainer add(Object... objects) {
- added.addAll(Arrays.asList(objects));
- return null; // not used anyway
- }
-
- @Override
- public ComponentContainer addSingletons(Iterable<?> components) {
- for (Object component : components) {
- added.add(component);
- }
- return null; // not used anyway
- }
-
- @Override
- public <T> T getComponentByType(Class<T> type) {
- for (Object add : added) {
- if (add.getClass().getSimpleName().contains(type.getSimpleName())) {
- return (T) add;
- }
- }
- return null;
- }
-
- @Override
- public <T> List<T> getComponentsByType(final Class<T> type) {
- return added.stream()
- .filter(input -> input.getClass().getSimpleName().contains(type.getSimpleName()))
- .map(input -> (T) input)
- .collect(Collectors.toList());
- }
- }
-
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.ce.task.projectanalysis.filesystem;
+
+import org.apache.commons.io.FileUtils;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import org.sonar.api.utils.TempFolder;
+import org.sonar.server.platform.ServerFileSystem;
+
+import java.io.File;
+
+public class ComputationTempFolderProviderTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ private final ComputationTempFolderProvider underTest = new ComputationTempFolderProvider();
+
+ @Test
+ public void existing_temp_dir() throws Exception {
+ ServerFileSystem fs = mock(ServerFileSystem.class);
+ File tmpDir = temp.newFolder();
+ when(fs.getTempDir()).thenReturn(tmpDir);
+
+ TempFolder folder = underTest.provide(fs);
+ assertThat(folder).isNotNull();
+ File newDir = folder.newDir();
+ assertThat(newDir).exists().isDirectory();
+ assertThat(newDir.getParentFile().getCanonicalPath()).startsWith(tmpDir.getCanonicalPath());
+ }
+
+ @Test
+ public void create_temp_dir_if_missing() throws Exception {
+ ServerFileSystem fs = mock(ServerFileSystem.class);
+ File tmpDir = temp.newFolder();
+ when(fs.getTempDir()).thenReturn(tmpDir);
+ FileUtils.forceDelete(tmpDir);
+
+ TempFolder folder = underTest.provide(fs);
+ assertThat(folder).isNotNull();
+ File newDir = folder.newDir();
+ assertThat(newDir).exists().isDirectory();
+ assertThat(newDir.getParentFile().getCanonicalPath()).startsWith(tmpDir.getCanonicalPath());
+ }
+}
*/
package org.sonar.ce.task.projectanalysis.step;
-import com.google.common.collect.Lists;
import org.junit.Test;
import org.sonar.ce.task.container.TaskContainerImpl;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.ce.task.step.ComputationStep;
+import org.sonar.core.platform.SpringComponentContainer;
+import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
@Test
public void instances_throws_ISE_if_container_does_not_have_any_step() {
- assertThatThrownBy(() -> {
- TaskContainerImpl computeEngineContainer = new TaskContainerImpl(new ComponentContainer(), container -> {
- // do nothing
- });
-
- Lists.newArrayList(new ReportComputationSteps(computeEngineContainer).instances());
- })
+ TaskContainerImpl computeEngineContainer = new TaskContainerImpl(new SpringComponentContainer(), container -> {
+ // do nothing
+ });
+ Iterable<ComputationStep> instances = new ReportComputationSteps(computeEngineContainer).instances();
+ assertThatThrownBy(() -> newArrayList(instances))
.isInstanceOf(IllegalStateException.class)
- .hasMessage("Component not found: " + ExtractReportStep.class);
+ .hasMessageContaining(ExtractReportStep.class.getName());
}
@Test
public void instances_throws_ISE_if_container_does_not_have_second_step() {
- assertThatThrownBy(() -> {
- final ExtractReportStep reportExtractionStep = mock(ExtractReportStep.class);
- ComponentContainer componentContainer = new ComponentContainer() {
- {
- addSingleton(reportExtractionStep);
- }
- };
- TaskContainerImpl computeEngineContainer = new TaskContainerImpl(componentContainer, container -> {
- // do nothing
- });
-
- Lists.newArrayList(new ReportComputationSteps(computeEngineContainer).instances());
- })
+ ExtractReportStep reportExtractionStep = mock(ExtractReportStep.class);
+ SpringComponentContainer componentContainer = new SpringComponentContainer() {
+ {
+ add(reportExtractionStep);
+ }
+ }.startComponents();
+ TaskContainerImpl computeEngineContainer = new TaskContainerImpl(componentContainer, container -> {
+ // do nothing
+ });
+ computeEngineContainer.startComponents();
+ Iterable<ComputationStep> instances = new ReportComputationSteps(computeEngineContainer).instances();
+ assertThatThrownBy(() -> newArrayList(instances))
.isInstanceOf(IllegalStateException.class)
- .hasMessage("Component not found: class org.sonar.ce.task.projectanalysis.step.PersistScannerContextStep");
+ .hasMessageContaining("org.sonar.ce.task.projectanalysis.step.PersistScannerContextStep");
}
}
@Rule
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
- CoverageMeasuresStep underTest = new CoverageMeasuresStep(treeRootHolder, metricRepository, measureRepository);
+ CoverageMeasuresStep underTest = new CoverageMeasuresStep(treeRootHolder, metricRepository, measureRepository, null);
@Before
public void setUp() {
package org.sonar.ce.task.projectanalysis.taskprocessor;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class AuditPurgeTaskModuleTest {
-
@Test
public void verifyCountOfAddedComponents() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new AuditPurgeTaskModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 1);
+ assertThat(container.getAddedObjects()).hasSize(1);
}
-
}
import org.sonar.ce.task.CeTask;
import org.sonar.ce.task.container.TaskContainer;
import org.sonar.ce.task.step.ComputationStep;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
import static org.sonar.ce.task.projectanalysis.taskprocessor.AuditPurgeTaskProcessor.AuditPurgeComputationSteps;
import static org.sonar.db.ce.CeTaskTypes.AUDIT_PURGE;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class AuditPurgeTaskProcessorTest {
- private ComponentContainer ceEngineContainer = Mockito.mock(ComponentContainer.class);
-
- private AuditPurgeTaskProcessor underTest = new AuditPurgeTaskProcessor(ceEngineContainer);
- private TaskContainer container = Mockito.spy(TaskContainer.class);
+ private final SpringComponentContainer ceEngineContainer = mock(SpringComponentContainer.class);
+ private final AuditPurgeTaskProcessor underTest = new AuditPurgeTaskProcessor(ceEngineContainer);
+ private final TaskContainer container = Mockito.spy(TaskContainer.class);
@Test
public void getHandledCeTaskTypes() {
import org.sonar.ce.task.CeTask;
import org.sonar.ce.task.container.TaskContainer;
import org.sonar.ce.task.step.ComputationStep;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
import static org.sonar.ce.task.projectanalysis.taskprocessor.IssueSyncTaskProcessor.SyncComputationSteps;
import static org.sonar.db.ce.CeTaskTypes.BRANCH_ISSUE_SYNC;
public class IssueSyncTaskProcessorTest {
- private ComponentContainer ceEngineContainer = Mockito.mock(ComponentContainer.class);
-
- private IssueSyncTaskProcessor underTest = new IssueSyncTaskProcessor(ceEngineContainer);
- private TaskContainer container = Mockito.spy(TaskContainer.class);
+ private final SpringComponentContainer ceEngineContainer = mock(SpringComponentContainer.class);
+ private final IssueSyncTaskProcessor underTest = new IssueSyncTaskProcessor(ceEngineContainer);
+ private final TaskContainer container = Mockito.spy(TaskContainer.class);
@Test
public void getHandledCeTaskTypes() {
import org.sonar.ce.task.container.TaskContainer;
import org.sonar.ce.task.container.TaskContainerImpl;
import org.sonar.ce.task.projectanalysis.step.ComplexityMeasuresStep;
-import org.sonar.ce.task.projectexport.steps.LoadProjectStep;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.ce.task.step.ComputationStep;
+import org.sonar.core.platform.SpringComponentContainer;
import static com.google.common.collect.ImmutableList.copyOf;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class ProjectExportComputationStepsTest {
-
- private TaskContainer container = mock(TaskContainer.class);
- private ProjectExportComputationSteps underTest = new ProjectExportComputationSteps(container);
+ private final TaskContainer container = mock(TaskContainer.class);
+ private final ProjectExportComputationSteps underTest = new ProjectExportComputationSteps(container);
@Test
public void count_step_classes() {
@Test
public void instances_throws_ISE_if_steps_do_not_exist_in_container() {
- assertThatThrownBy(() -> copyOf(underTest.instances()))
+ when(container.getComponentByType(any())).thenThrow(new IllegalStateException("Error"));
+ Iterable<ComputationStep> instances = underTest.instances();
+ assertThatThrownBy(() -> copyOf(instances))
.isInstanceOf(IllegalStateException.class)
- .hasMessage("Component not found: " + LoadProjectStep.class);
+ .hasMessage("Error");
}
@Test
public void instances_throws_ISE_if_container_does_not_have_second_step() {
- assertThatThrownBy(() -> {
- final ComplexityMeasuresStep reportExtractionStep = mock(ComplexityMeasuresStep.class);
-
- ComponentContainer componentContainer = new ComponentContainer() {
- {
- addSingleton(reportExtractionStep);
- }
- };
- TaskContainerImpl computeEngineContainer = new TaskContainerImpl(componentContainer, container -> {
- // do nothing
- });
+ ComplexityMeasuresStep reportExtractionStep = mock(ComplexityMeasuresStep.class);
- Lists.newArrayList(new ProjectExportComputationSteps(computeEngineContainer).instances());
- })
+ SpringComponentContainer componentContainer = new SpringComponentContainer() {
+ {
+ add(reportExtractionStep);
+ }
+ }.startComponents();
+ TaskContainerImpl computeEngineContainer = new TaskContainerImpl(componentContainer, container -> {
+ // do nothing
+ });
+ computeEngineContainer.startComponents();
+ Iterable<ComputationStep> instances = new ProjectExportComputationSteps(computeEngineContainer).instances();
+ assertThatThrownBy(() -> Lists.newArrayList(instances))
.isInstanceOf(IllegalStateException.class)
- .hasMessage("Component not found: class org.sonar.ce.task.projectexport.steps.LoadProjectStep");
+ .hasMessageContaining("class org.sonar.ce.task.projectexport.steps.LoadProjectStep");
}
}
*/
package org.sonar.ce.task.projectexport;
-import com.google.common.base.Predicate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
import org.junit.Test;
-import org.picocontainer.PicoContainer;
-import org.sonar.ce.task.container.TaskContainer;
+import org.sonar.ce.task.projectanalysis.task.ListTaskContainer;
import org.sonar.ce.task.projectexport.taskprocessor.ProjectDescriptor;
import org.sonar.ce.task.setting.SettingsLoader;
-import org.sonar.ce.task.step.ComputationStep;
-import org.sonar.core.platform.ComponentContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class ProjectExportContainerPopulatorTest {
-
- private static final int COMPONENTS_BY_DEFAULT_IN_CONTAINER = 2;
-
private final ProjectDescriptor descriptor = new ProjectDescriptor("project_uuid", "project_key", "Project Name");
private final ProjectExportContainerPopulator underTest = new ProjectExportContainerPopulator(descriptor);
@Test
public void test_populateContainer() {
- RecorderTaskContainer container = new RecorderTaskContainer();
+ ListTaskContainer container = new ListTaskContainer();
underTest.populateContainer(container);
- assertThat(container.addedComponents)
- .hasSize(COMPONENTS_BY_DEFAULT_IN_CONTAINER + 8)
+ assertThat(container.getAddedComponents())
+ .hasSize(29)
.contains(descriptor, SettingsLoader.class);
}
-
- private static class RecorderTaskContainer implements TaskContainer {
- private final List<Object> addedComponents = new ArrayList<>();
-
- @Override
- public ComponentContainer add(Object... objects) {
- addedComponents.addAll(Arrays.asList(objects));
- // not used anyway
- return null;
- }
-
- @Override
- public ComponentContainer addSingletons(Iterable<?> components) {
- List<Object> filteredComponents = StreamSupport.stream(components.spliterator(), false)
- .filter((Predicate<Object>) input -> !(input instanceof Class) || !ComputationStep.class.isAssignableFrom((Class<?>) input))
- .collect(Collectors.toList());
-
- addedComponents.addAll(filteredComponents);
- // not used anyway
- return null;
- }
-
- @Override
- public ComponentContainer getParent() {
- throw new UnsupportedOperationException("getParent is not implemented");
- }
-
- @Override
- public void bootup() {
- throw new UnsupportedOperationException("bootup is not implemented");
- }
-
- @Override
- public void close() {
- throw new UnsupportedOperationException("close is not implemented");
- }
-
- @Override
- public PicoContainer getPicoContainer() {
- throw new UnsupportedOperationException("getParent is not implemented");
- }
-
- @Override
- public <T> T getComponentByType(Class<T> type) {
- throw new UnsupportedOperationException("getParent is not implemented");
- }
-
- @Override
- public <T> List<T> getComponentsByType(final Class<T> type) {
- throw new UnsupportedOperationException("getParent is not implemented");
- }
- }
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.ce.task.projectanalysis.task;
+
+import com.google.common.collect.Iterables;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import org.sonar.ce.task.container.TaskContainer;
+import org.sonar.core.platform.Module;
+import org.sonar.core.platform.SpringComponentContainer;
+
+public class ListTaskContainer implements TaskContainer {
+ private final List<Object> addedComponents = new ArrayList<>();
+
+ @Override
+ public SpringComponentContainer add(Object... objects) {
+ for (Object o : objects) {
+ if (o instanceof Module) {
+ ((Module) o).configure(this);
+ } else if (o instanceof Iterable) {
+ add(Iterables.toArray((Iterable<?>) o, Object.class));
+ } else {
+ this.addedComponents.add(o);
+ }
+ }
+ // not used anyway
+ return null;
+ }
+
+ public List<Object> getAddedComponents() {
+ return addedComponents;
+ }
+
+ @Override
+ public SpringComponentContainer getParent() {
+ throw new UnsupportedOperationException("getParent is not implemented");
+ }
+
+ @Override
+ public void bootup() {
+ throw new UnsupportedOperationException("bootup is not implemented");
+ }
+
+ @Override
+ public void close() {
+ throw new UnsupportedOperationException("close is not implemented");
+ }
+
+ @Override
+ public <T> T getComponentByType(Class<T> type) {
+ throw new UnsupportedOperationException("getParent is not implemented");
+ }
+
+ @Override public <T> Optional<T> getOptionalComponentByType(Class<T> type) {
+ throw new UnsupportedOperationException("getParent is not implemented");
+ }
+
+ @Override
+ public <T> List<T> getComponentsByType(final Class<T> type) {
+ throw new UnsupportedOperationException("getParent is not implemented");
+ }
+}
// please keep the list grouped by configuration and ordered by name
compile 'com.google.guava:guava'
- compile 'org.picocontainer:picocontainer'
compile 'org.slf4j:jul-to-slf4j'
compile 'org.slf4j:slf4j-api'
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.ce.task.container;
+
+import javax.annotation.Nullable;
+import org.sonar.core.platform.SpringInitStrategy;
+import org.springframework.beans.factory.config.BeanDefinition;
+
+public class LazyUnlessEagerAnnotationStrategy extends SpringInitStrategy {
+ @Override
+ protected boolean isLazyInit(BeanDefinition beanDefinition, @Nullable Class<?> clazz) {
+ return clazz == null || clazz.getAnnotation(EagerStart.class) == null;
+ }
+}
*/
package org.sonar.ce.task.container;
-import org.picocontainer.PicoContainer;
import org.sonar.ce.task.CeTask;
-import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.Container;
+import org.sonar.core.platform.ExtensionContainer;
/**
- * The Compute Engine task container. Created for a specific parent {@link ComponentContainer} and a specific {@link CeTask}.
+ * The Compute Engine task container. Created for a specific parent {@link ExtensionContainer} and a specific {@link CeTask}.
*/
public interface TaskContainer extends Container, AutoCloseable {
- ComponentContainer getParent();
+ ExtensionContainer getParent();
/**
* Starts task container, starting any startable component in it.
*/
@Override
void close();
-
- /**
- * Access to the underlying pico container.
- */
- PicoContainer getPicoContainer();
-
}
*/
package org.sonar.ce.task.container;
-import java.util.List;
-import org.picocontainer.ComponentAdapter;
-import org.picocontainer.DefaultPicoContainer;
-import org.picocontainer.LifecycleStrategy;
-import org.picocontainer.MutablePicoContainer;
-import org.picocontainer.behaviors.OptInCaching;
-import org.picocontainer.monitors.NullComponentMonitor;
-import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.ContainerPopulator;
-import org.sonar.core.platform.Module;
-import org.sonar.core.platform.StartableCloseableSafeLifecyleStrategy;
+import org.sonar.core.platform.SpringComponentContainer;
import static java.util.Objects.requireNonNull;
-public class TaskContainerImpl extends ComponentContainer implements TaskContainer {
-
- public TaskContainerImpl(ComponentContainer parent, ContainerPopulator<TaskContainer> populator) {
- super(createContainer(requireNonNull(parent)), parent.getComponentByType(PropertyDefinitions.class));
+public class TaskContainerImpl extends SpringComponentContainer implements TaskContainer {
+ public TaskContainerImpl(SpringComponentContainer parent, ContainerPopulator<TaskContainer> populator) {
+ super(parent, new LazyUnlessEagerAnnotationStrategy());
populateContainer(requireNonNull(populator));
}
private void populateContainer(ContainerPopulator<TaskContainer> populator) {
populator.populateContainer(this);
- populateFromModules();
- }
-
- private void populateFromModules() {
- List<Module> modules = getComponentsByType(Module.class);
- for (Module module : modules) {
- module.configure(this);
- }
- }
-
- /**
- * 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) {
- LifecycleStrategy lifecycleStrategy = new StartableCloseableSafeLifecyleStrategy() {
- @Override
- public boolean isLazy(ComponentAdapter<?> adapter) {
- return adapter.getComponentImplementation().getAnnotation(EagerStart.class) == null;
- }
- };
-
- return new DefaultPicoContainer(new OptInCaching(), lifecycleStrategy, parent.getPicoContainer(), new NullComponentMonitor());
}
@Override
*/
package org.sonar.ce.task.setting;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.config.internal.Settings;
import org.sonar.ce.task.container.EagerStart;
import org.sonar.api.utils.log.Loggers;
import org.sonar.ce.task.CeTaskInterrupter;
import org.sonar.core.util.logs.Profiler;
+import org.springframework.beans.factory.annotation.Autowired;
import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
@CheckForNull
private final Listener listener;
- /**
- * Used when no {@link ComputationStepExecutor.Listener} is available in pico
- * container.
- */
+ @Autowired(required = false)
public ComputationStepExecutor(ComputationSteps steps, CeTaskInterrupter taskInterrupter) {
this(steps, taskInterrupter, null);
}
+ @Autowired(required = false)
public ComputationStepExecutor(ComputationSteps steps, CeTaskInterrupter taskInterrupter, @Nullable Listener listener) {
this.steps = steps;
this.taskInterrupter = taskInterrupter;
package org.sonar.ce.task.step;
import org.sonar.api.ce.ComputeEngineSide;
+import org.springframework.beans.factory.annotation.Autowired;
/**
* Execute {@link StatelessInitExtension} instances in no specific order.
private final StatelessInitExtension[] extensions;
+ @Autowired(required = false)
public ExecuteStatelessInitExtensionsStep(StatelessInitExtension[] extensions) {
this.extensions = extensions;
}
/**
* Used when zero {@link StatelessInitExtension} are registered into container.
*/
+ @Autowired(required = false)
public ExecuteStatelessInitExtensionsStep() {
this(new StatelessInitExtension[0]);
}
*/
package org.sonar.ce.task.container;
+import org.junit.Before;
import org.junit.Test;
-import org.picocontainer.Startable;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.api.Startable;
import org.sonar.core.platform.ContainerPopulator;
+import org.sonar.core.platform.SpringComponentContainer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.verify;
public class TaskContainerImplTest {
- private ComponentContainer parent = new ComponentContainer();
- private ContainerPopulator<TaskContainer> populator = spy(new DummyContainerPopulator());
+ private final SpringComponentContainer parent = new SpringComponentContainer();
+ private final ContainerPopulator<TaskContainer> populator = spy(new DummyContainerPopulator());
+
+ @Before
+ public void before() {
+ parent.startComponents();
+ }
@Test
public void constructor_fails_fast_on_null_container() {
@Test
public void constructor_fails_fast_on_null_item() {
- assertThatThrownBy(() -> new TaskContainerImpl(new ComponentContainer(), null))
+ SpringComponentContainer c = new SpringComponentContainer();
+ assertThatThrownBy(() -> new TaskContainerImpl(c, null))
.isInstanceOf(NullPointerException.class);
}
verify(populator).populateContainer(ceContainer);
}
- @Test
- public void ce_container_is_not_child_of_specified_container() {
- TaskContainerImpl ceContainer = new TaskContainerImpl(parent, populator);
-
- assertThat(parent.getChildren()).isEmpty();
- verify(populator).populateContainer(ceContainer);
- }
-
@Test
public void bootup_starts_components_lazily_unless_they_are_annotated_with_EagerStart() {
- final DefaultStartable defaultStartable = new DefaultStartable();
- final EagerStartable eagerStartable = new EagerStartable();
+ DefaultStartable defaultStartable = new DefaultStartable();
+ EagerStartable eagerStartable = new EagerStartable();
TaskContainerImpl ceContainer = new TaskContainerImpl(parent, container -> {
container.add(defaultStartable);
container.add(eagerStartable);
compile 'commons-io:commons-io'
compile 'org.apache.commons:commons-dbcp2'
compile 'org.nanohttpd:nanohttpd'
- compile 'org.picocontainer:picocontainer'
compile project(':server:sonar-ce-common')
compile project(':server:sonar-ce-task')
compile project(':server:sonar-ce-task-projectanalysis')
testCompile 'org.awaitility:awaitility'
testCompile 'org.mockito:mockito-core'
testCompile 'org.slf4j:slf4j-api'
-
+
testCompile testFixtures(project(':server:sonar-db-dao'))
}
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.ce.taskprocessor.CeWorker;
import javax.annotation.Nullable;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.MessageException;
+import org.springframework.beans.factory.annotation.Autowired;
import static java.lang.String.format;
import static org.sonar.process.ProcessProperties.Property.CE_GRACEFUL_STOP_TIMEOUT;
private final long gracefulStopTimeoutInMs;
private int workerCount;
+ @Autowired(required = false)
public CeConfigurationImpl(Configuration configuration) {
this(configuration, null);
}
+ @Autowired(required = false)
public CeConfigurationImpl(Configuration configuration, @Nullable WorkerCountProvider workerCountProvider) {
this.workerCountProvider = workerCountProvider;
this.gracefulStopTimeoutInMs = configuration.getLong(CE_GRACEFUL_STOP_TIMEOUT.getKey())
*/
package org.sonar.ce.configuration;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.Plugin;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.platform.ExplodedPlugin;
import org.sonar.api.internal.SonarRuntimeImpl;
import org.sonar.api.profiles.XMLProfileParser;
import org.sonar.api.profiles.XMLProfileSerializer;
-import org.sonar.api.resources.Languages;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.rules.AnnotationRuleParser;
import org.sonar.api.server.profile.BuiltInQualityProfileAnnotationLoader;
import org.sonar.core.config.CorePropertyDefinitions;
import org.sonar.core.extension.CoreExtensionRepositoryImpl;
import org.sonar.core.extension.CoreExtensionsLoader;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.language.LanguagesProvider;
+import org.sonar.core.platform.Container;
import org.sonar.core.platform.EditionProvider;
-import org.sonar.core.platform.Module;
import org.sonar.core.platform.PlatformEditionProvider;
import org.sonar.core.platform.PluginClassLoader;
import org.sonar.core.platform.PluginClassloaderFactory;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.core.util.UuidFactoryImpl;
import org.sonar.db.DBSessionsImpl;
import org.sonar.db.DaoModule;
import org.sonar.db.DbClient;
import org.sonar.db.DefaultDatabase;
import org.sonar.db.MyBatis;
-import org.sonar.db.audit.AuditPersister;
import org.sonar.db.audit.NoOpAuditPersister;
import org.sonar.db.purge.PurgeProfiler;
import org.sonar.process.NetworkUtilsImpl;
public class ComputeEngineContainerImpl implements ComputeEngineContainer {
- private ComputeEngineStatus computeEngineStatus;
+ private ComputeEngineStatus computeEngineStatus = null;
@CheckForNull
- private ComponentContainer level1;
+ private SpringComponentContainer level1 = null;
@CheckForNull
- private ComponentContainer level4;
+ private SpringComponentContainer level4 = null;
@Override
public void setComputeEngineStatus(ComputeEngineStatus computeEngineStatus) {
@Override
public ComputeEngineContainer start(Props props) {
- this.level1 = new ComponentContainer();
+ this.level1 = new SpringComponentContainer();
populateLevel1(this.level1, props, requireNonNull(computeEngineStatus));
- configureFromModules(this.level1);
startLevel1(this.level1);
- ComponentContainer level2 = this.level1.createChild();
+ SpringComponentContainer level2 = this.level1.createChild();
populateLevel2(level2);
- configureFromModules(level2);
startLevel2(level2);
- ComponentContainer level3 = level2.createChild();
+ SpringComponentContainer level3 = level2.createChild();
populateLevel3(level3);
- configureFromModules(level3);
startLevel3(level3);
this.level4 = level3.createChild();
populateLevel4(this.level4, props);
- configureFromModules(this.level4);
startLevel4(this.level4);
startupTasks();
return this;
}
- private static void startLevel1(ComponentContainer level1) {
+ private static void startLevel1(SpringComponentContainer level1) {
+ level1.startComponents();
level1.getComponentByType(CoreExtensionsLoader.class)
.load();
level1.getComponentByType(CECoreExtensionsInstaller.class)
.install(level1, hasPlatformLevel(1), noAdditionalSideFilter());
-
- if (level1.getComponentByType(AuditPersister.class) == null) {
- level1.add(NoOpAuditPersister.class);
- }
- level1.startComponents();
}
- private static void startLevel2(ComponentContainer level2) {
- level2.getComponentByType(CECoreExtensionsInstaller.class)
+ private static void startLevel2(SpringComponentContainer level2) {
+ level2.getParent().getComponentByType(CECoreExtensionsInstaller.class)
.install(level2, hasPlatformLevel(2), noAdditionalSideFilter());
level2.startComponents();
}
- private static void startLevel3(ComponentContainer level3) {
- level3.getComponentByType(CECoreExtensionsInstaller.class)
+ private static void startLevel3(SpringComponentContainer level3) {
+ level3.getParent().getComponentByType(CECoreExtensionsInstaller.class)
.install(level3, hasPlatformLevel(3), noAdditionalSideFilter());
level3.startComponents();
}
- private static void startLevel4(ComponentContainer level4) {
- level4.getComponentByType(CECoreExtensionsInstaller.class)
+ private static void startLevel4(SpringComponentContainer level4) {
+ level4.getParent().getComponentByType(CECoreExtensionsInstaller.class)
.install(level4, hasPlatformLevel4OrNone(), noAdditionalSideFilter());
- level4.getComponentByType(ServerExtensionInstaller.class)
+ level4.getParent().getComponentByType(ServerExtensionInstaller.class)
.installExtensions(level4);
level4.startComponents();
}
private void startupTasks() {
- ComponentContainer startupLevel = this.level4.createChild();
+ SpringComponentContainer startupLevel = this.level4.createChild();
startupLevel.add(startupComponents());
startupLevel.startComponents();
// done in PlatformLevelStartup
}
@VisibleForTesting
- protected ComponentContainer getComponentContainer() {
+ protected SpringComponentContainer getComponentContainer() {
return level4;
}
- private static void populateLevel1(ComponentContainer container, Props props, ComputeEngineStatus computeEngineStatus) {
+ private static void populateLevel1(Container container, Props props, ComputeEngineStatus computeEngineStatus) {
Version apiVersion = MetadataLoader.loadVersion(System2.INSTANCE);
SonarEdition edition = MetadataLoader.loadEdition(System2.INSTANCE);
container.add(
Clock.systemDefaultZone(),
// DB
- DaoModule.class,
+ new DaoModule(),
ReadOnlyPropertiesDao.class,
DBSessionsImpl.class,
DbClient.class,
// Elasticsearch
- EsModule.class,
+ new EsModule(),
// rules/qprofiles
RuleIndex.class,
new OkHttpClientProvider(),
computeEngineStatus,
+ NoOpAuditPersister.class,
CoreExtensionRepositoryImpl.class,
CoreExtensionsLoader.class,
container.add(toArray(CorePropertyDefinitions.all()));
}
- private static void populateLevel2(ComponentContainer container) {
+ private static void populateLevel2(Container container) {
container.add(
- MigrationConfigurationModule.class,
+ new MigrationConfigurationModule(),
DatabaseVersion.class,
DatabaseCompatibility.class,
);
}
- private static void populateLevel3(ComponentContainer container) {
+ private static void populateLevel3(Container container) {
container.add(
new StartupMetadataProvider(),
JdbcUrlSanitizer.class,
SynchronousAsyncExecution.class);
}
- private static void populateLevel4(ComponentContainer container, Props props) {
+ private static void populateLevel4(Container container, Props props) {
container.add(
ResourceTypes.class,
DefaultResourceTypes.get(),
RuleIndexer.class,
// languages
- Languages.class, // used by CommonRuleDefinitionsImpl
+ // used by CommonRuleDefinitionsImpl
+ LanguagesProvider.class,
// measure
MetricFinder.class,
NewIssuesNotificationHandler.newMetadata(),
MyNewIssuesNotificationHandler.class,
MyNewIssuesNotificationHandler.newMetadata(),
- IssuesChangesNotificationModule.class,
+ new IssuesChangesNotificationModule(),
// Notifications
QGChangeEmailTemplate.class,
NotificationService.class,
DefaultNotificationManager.class,
EmailNotificationChannel.class,
- ReportAnalysisFailureNotificationModule.class,
+ new ReportAnalysisFailureNotificationModule(),
// System
ServerLogging.class,
CoreExtensionStopper.class,
// Compute engine (must be after Views and Developer Cockpit)
- CeConfigurationModule.class,
- CeQueueModule.class,
- CeHttpModule.class,
- CeTaskCommonsModule.class,
- ProjectAnalysisTaskModule.class,
- IssueSyncTaskModule.class,
- AuditPurgeTaskModule.class,
- CeTaskProcessorModule.class,
+ new CeConfigurationModule(),
+ new CeQueueModule(),
+ new CeHttpModule(),
+ new CeTaskCommonsModule(),
+ new ProjectAnalysisTaskModule(),
+ new IssueSyncTaskModule(),
+ new AuditPurgeTaskModule(),
+ new CeTaskProcessorModule(),
OfficialDistribution.class,
InternalPropertiesImpl.class,
ProjectConfigurationFactory.class,
// webhooks
- WebhookModule.class,
+ new WebhookModule(),
QualityGateFinder.class,
QualityGateEvaluatorImpl.class
CEQueueStatusImpl.class);
} else if (props.valueAsBoolean(CLUSTER_ENABLED.getKey())) {
container.add(
- CeCleaningModule.class,
+ new CeCleaningModule(),
// system health
CeDistributedInformationImpl.class,
DistributedCEQueueStatusImpl.class);
} else {
container.add(
- CeCleaningModule.class,
+ new CeCleaningModule(),
StandaloneCeDistributedInformation.class,
CEQueueStatusImpl.class);
}
private static Object[] toArray(List<?> list) {
return list.toArray(new Object[list.size()]);
}
-
- private static void configureFromModules(ComponentContainer container) {
- List<Module> modules = container.getComponentsByType(Module.class);
- for (Module module : modules) {
- module.configure(container);
- }
- }
}
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.slf4j.LoggerFactory;
import org.sonar.process.sharedmemoryfile.DefaultProcessCommands;
*
* <p>
* Method {@link #register(ActionRegistry)} of the action will be called right before the HTTP server is started (server
- * is started by the Pico Container). It's the action's responsibility to call the method
+ * is started by the ioc container). It's the action's responsibility to call the method
* {@link ActionRegistry#register(ActionRegistry)} to register itself for a given path.
* </p>
* <p>
package org.sonar.ce.monitoring;
import org.apache.commons.dbcp2.BasicDataSource;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.db.DbClient;
import org.sonar.process.Jmx;
import org.sonar.process.systeminfo.SystemInfoSection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.ce.configuration.CeConfiguration;
import org.sonar.ce.taskprocessor.CeWorker;
import org.sonar.ce.taskprocessor.CeWorkerController;
import org.sonar.api.SonarRuntime;
import org.sonar.api.ce.ComputeEngineSide;
+import org.sonar.api.config.Configuration;
import org.sonar.core.platform.PluginRepository;
import org.sonar.server.plugins.ServerExtensionInstaller;
import static java.util.Collections.singleton;
public class ComputeEngineExtensionInstaller extends ServerExtensionInstaller {
- public ComputeEngineExtensionInstaller(SonarRuntime sonarRuntime, PluginRepository pluginRepository) {
- super(sonarRuntime, pluginRepository, singleton(ComputeEngineSide.class));
+ public ComputeEngineExtensionInstaller(Configuration configuration, SonarRuntime sonarRuntime, PluginRepository pluginRepository) {
+ super(configuration, sonarRuntime, pluginRepository, singleton(ComputeEngineSide.class));
}
}
*/
package org.sonar.ce.platform;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.server.platform.db.migration.version.DatabaseVersion;
import static com.google.common.base.Preconditions.checkState;
*/
package org.sonar.ce.taskprocessor;
-import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.System2;
import org.sonar.ce.task.CeTaskInterrupter;
+import org.springframework.context.annotation.Bean;
import static com.google.common.base.Preconditions.checkState;
-public class CeTaskInterrupterProvider extends ProviderAdapter {
+public class CeTaskInterrupterProvider {
private static final String PROPERTY_CE_TASK_TIMEOUT = "sonar.ce.task.timeoutSeconds";
- private CeTaskInterrupter instance;
-
+ @Bean("CeTaskInterrupter")
public CeTaskInterrupter provide(Configuration configuration, CeWorkerController ceWorkerController, System2 system2) {
- if (instance == null) {
- instance = configuration.getLong(PROPERTY_CE_TASK_TIMEOUT)
- .filter(timeOutInSeconds -> {
- checkState(timeOutInSeconds >= 1, "The property '%s' must be a long value >= 1. Got '%s'", PROPERTY_CE_TASK_TIMEOUT, timeOutInSeconds);
- return true;
- })
- .map(timeOutInSeconds -> (CeTaskInterrupter) new TimeoutCeTaskInterrupter(timeOutInSeconds * 1_000L, ceWorkerController, system2))
- .orElseGet(SimpleCeTaskInterrupter::new);
- }
- return instance;
+ return configuration.getLong(PROPERTY_CE_TASK_TIMEOUT)
+ .filter(timeOutInSeconds -> {
+ checkState(timeOutInSeconds >= 1, "The property '%s' must be a long value >= 1. Got '%s'", PROPERTY_CE_TASK_TIMEOUT, timeOutInSeconds);
+ return true;
+ })
+ .map(timeOutInSeconds -> (CeTaskInterrupter) new TimeoutCeTaskInterrupter(timeOutInSeconds * 1_000L, ceWorkerController, system2))
+ .orElseGet(SimpleCeTaskInterrupter::new);
}
}
/**
* {@link CeTaskProcessorRepository} implementation which provides access to the {@link CeTaskProcessor} existing in the
- * PicoContainer the current object belongs to.
+ * ioc container the current object belongs to.
*/
public class CeTaskProcessorRepositoryImpl implements CeTaskProcessorRepository {
private final Map<String, CeTaskProcessor> taskProcessorByCeTaskType;
import org.sonar.ce.queue.InternalCeQueue;
import org.sonar.core.util.UuidFactory;
import org.sonar.core.util.stream.MoreCollectors;
+import org.springframework.beans.factory.annotation.Autowired;
public class CeWorkerFactoryImpl implements CeWorkerFactory {
private final UuidFactory uuidFactory;
private Set<CeWorker> ceWorkers = Collections.emptySet();
/**
- * Used by Pico when there is no {@link CeWorker.ExecutionListener} in the container.
+ * Used by the ioc container when there is no {@link CeWorker.ExecutionListener} in the container.
*/
- public CeWorkerFactoryImpl(InternalCeQueue queue, CeTaskProcessorRepository taskProcessorRepository,
- UuidFactory uuidFactory, CeWorkerController ceWorkerController) {
+ @Autowired(required = false)
+ public CeWorkerFactoryImpl(InternalCeQueue queue, CeTaskProcessorRepository taskProcessorRepository, UuidFactory uuidFactory, CeWorkerController ceWorkerController) {
this(queue, taskProcessorRepository, uuidFactory, ceWorkerController, new CeWorker.ExecutionListener[0]);
}
- public CeWorkerFactoryImpl(InternalCeQueue queue, CeTaskProcessorRepository taskProcessorRepository,
- UuidFactory uuidFactory, CeWorkerController ceWorkerController,
+ @Autowired(required = false)
+ public CeWorkerFactoryImpl(InternalCeQueue queue, CeTaskProcessorRepository taskProcessorRepository, UuidFactory uuidFactory, CeWorkerController ceWorkerController,
CeWorker.ExecutionListener[] executionListeners) {
this.queue = queue;
this.taskProcessorRepository = taskProcessorRepository;
public class ComputeEngineImplTest {
- private ComputeEngineContainer computeEngineContainer = new NoOpComputeEngineContainer();
- private ComputeEngine underTest = new ComputeEngineImpl(new Props(new Properties()), computeEngineContainer);
+ private final ComputeEngineContainer computeEngineContainer = new NoOpComputeEngineContainer();
+ private final ComputeEngine underTest = new ComputeEngineImpl(new Props(new Properties()), computeEngineContainer);
@Test
public void startup_throws_ISE_when_called_twice() {
underTest.startup();
- assertThatThrownBy(() -> underTest.startup())
+ assertThatThrownBy(underTest::startup)
.isInstanceOf(IllegalStateException.class)
.hasMessage("startup() can not be called multiple times");
}
@Test
public void stopProcessing_throws_ISE_if_startup_was_not_called_before() {
- assertThatThrownBy(() -> underTest.stopProcessing())
+ assertThatThrownBy(underTest::stopProcessing)
.isInstanceOf(IllegalStateException.class)
.hasMessage("stopProcessing() must not be called before startup()");
}
underTest.startup();
underTest.shutdown();
- assertThatThrownBy(() -> underTest.stopProcessing())
+ assertThatThrownBy(underTest::stopProcessing)
.isInstanceOf(IllegalStateException.class)
.hasMessage("stopProcessing() can not be called after shutdown()");
}
underTest.startup();
underTest.stopProcessing();
- assertThatThrownBy(() -> underTest.stopProcessing())
+ assertThatThrownBy(underTest::stopProcessing)
.isInstanceOf(IllegalStateException.class)
.hasMessage("stopProcessing() can not be called multiple times");
}
@Test
public void shutdown_throws_ISE_if_startup_was_not_called_before() {
- assertThatThrownBy(() -> underTest.shutdown())
+ assertThatThrownBy(underTest::shutdown)
.isInstanceOf(IllegalStateException.class)
.hasMessage("shutdown() must not be called before startup()");
}
underTest.startup();
underTest.shutdown();
- assertThatThrownBy(() -> underTest.shutdown())
+ assertThatThrownBy(underTest::shutdown)
.isInstanceOf(IllegalStateException.class)
.hasMessage("shutdown() can not be called multiple times");
}
import java.util.Date;
import java.util.Locale;
import java.util.Properties;
-import java.util.stream.Collectors;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.picocontainer.ComponentAdapter;
-import org.picocontainer.MutablePicoContainer;
import org.sonar.api.CoreProperties;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
-import org.sonar.ce.CeDistributedInformationImpl;
-import org.sonar.ce.StandaloneCeDistributedInformation;
import org.sonar.core.extension.ServiceLoaderWrapper;
import org.sonar.db.DbTester;
import org.sonar.db.property.PropertyDto;
import org.sonar.process.ProcessProperties;
import org.sonar.process.Props;
import org.sonar.server.property.InternalProperties;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static java.lang.String.valueOf;
import static org.assertj.core.api.Assertions.assertThat;
public DbTester db = DbTester.create(System2.INSTANCE);
- private ComputeEngineContainerImpl underTest;
- private ServiceLoaderWrapper serviceLoaderWrapper = mock(ServiceLoaderWrapper.class);
- private ProcessProperties processProperties = new ProcessProperties(serviceLoaderWrapper);
+ private final ServiceLoaderWrapper serviceLoaderWrapper = mock(ServiceLoaderWrapper.class);
+ private final ProcessProperties processProperties = new ProcessProperties(serviceLoaderWrapper);
+ private final ComputeEngineContainerImpl underTest = new ComputeEngineContainerImpl();
@Before
public void setUp() {
when(serviceLoaderWrapper.load()).thenReturn(ImmutableSet.of());
- underTest = new ComputeEngineContainerImpl();
underTest.setComputeEngineStatus(mock(ComputeEngineStatus.class));
}
underTest.start(new Props(properties));
- MutablePicoContainer picoContainer = underTest.getComponentContainer().getPicoContainer();
+ AnnotationConfigApplicationContext context = underTest.getComponentContainer().context();
try {
- assertThat(picoContainer.getComponentAdapters()).hasSizeGreaterThan(1);
- assertThat(picoContainer.getParent().getComponentAdapters()).hasSizeGreaterThan(1);
- assertThat(picoContainer.getParent().getParent().getComponentAdapters()).hasSizeGreaterThan(1);
- assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSizeGreaterThan(1);
- assertThat(
- picoContainer.getComponentAdapters().stream()
- .map(ComponentAdapter::getComponentImplementation)
- .collect(Collectors.toList())).doesNotContain(
- (Class) CeDistributedInformationImpl.class).contains(
- StandaloneCeDistributedInformation.class);
- assertThat(picoContainer.getParent().getParent().getParent().getParent()).isNull();
+ assertThat(context.getBeanDefinitionNames()).hasSizeGreaterThan(1);
+ assertThat(context.getParent().getBeanDefinitionNames()).hasSizeGreaterThan(1);
+ assertThat(context.getParent().getParent().getBeanDefinitionNames()).hasSizeGreaterThan(1);
+ assertThat(context.getParent().getParent().getParent().getBeanDefinitionNames()).hasSizeGreaterThan(1);
+ assertThat(context.getParent().getParent().getParent().getParent()).isNull();
} finally {
underTest.stop();
}
- assertThat(picoContainer.getLifecycleState().isStarted()).isFalse();
- assertThat(picoContainer.getLifecycleState().isStopped()).isFalse();
- assertThat(picoContainer.getLifecycleState().isDisposed()).isTrue();
+ assertThat(context.isActive()).isFalse();
}
private String cleanJdbcUrl() {
import javax.management.InstanceNotFoundException;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
+import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
+import org.sonar.process.Jmx;
import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.ce.monitoring.CeDatabaseMBean.OBJECT_NAME;
public class CeDatabaseMBeanImplTest {
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
- private CeDatabaseMBeanImpl underTest = new CeDatabaseMBeanImpl(dbTester.getDbClient());
+ private final CeDatabaseMBeanImpl underTest = new CeDatabaseMBeanImpl(dbTester.getDbClient());
+
+ @BeforeClass
+ public static void beforeClass() {
+ // if any other class starts a container where CeDatabaseMBeanImpl is added, it will have been registered
+ Jmx.unregister(OBJECT_NAME);
+ }
@Test
public void register_and_unregister() throws Exception {
@CheckForNull
private ObjectInstance getMBean() throws Exception {
try {
- return ManagementFactory.getPlatformMBeanServer().getObjectInstance(new ObjectName(CeDatabaseMBean.OBJECT_NAME));
+ return ManagementFactory.getPlatformMBeanServer().getObjectInstance(new ObjectName(OBJECT_NAME));
} catch (InstanceNotFoundException e) {
return null;
}
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import org.apache.commons.lang.RandomStringUtils;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.sonar.ce.configuration.CeConfiguration;
import org.sonar.ce.taskprocessor.CeWorker;
import org.sonar.ce.taskprocessor.CeWorkerController;
import org.sonar.ce.taskprocessor.CeWorkerFactory;
import org.sonar.core.util.stream.MoreCollectors;
+import org.sonar.process.Jmx;
import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import static org.sonar.ce.monitoring.CeTasksMBean.OBJECT_NAME;
public class CeTasksMBeanImplTest {
private static final long PENDING_COUNT = 2;
})
.collect(MoreCollectors.toSet());
- private CeWorkerController ceWorkerController = mock(CeWorkerController.class);
- private CeTasksMBeanImpl underTest = new CeTasksMBeanImpl(new DumbCEQueueStatus(), new DumbCeConfiguration(), new DumbCeWorkerFactory(), ceWorkerController);
+ private final CeWorkerController ceWorkerController = mock(CeWorkerController.class);
+ private final CeTasksMBeanImpl underTest = new CeTasksMBeanImpl(new DumbCEQueueStatus(), new DumbCeConfiguration(), new DumbCeWorkerFactory(), ceWorkerController);
+
+ @BeforeClass
+ public static void beforeClass() {
+ // if any other class starts a container where CeTasksMBeanImpl is added, it will have been registered
+ Jmx.unregister(OBJECT_NAME);
+ }
@Test
public void register_and_unregister() throws Exception {
@CheckForNull
private ObjectInstance getMBean() throws Exception {
try {
- return ManagementFactory.getPlatformMBeanServer().getObjectInstance(new ObjectName(CeTasksMBean.OBJECT_NAME));
+ return ManagementFactory.getPlatformMBeanServer().getObjectInstance(new ObjectName(OBJECT_NAME));
} catch (InstanceNotFoundException e) {
return null;
}
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.stream.Stream;
+
import org.junit.Test;
import org.sonar.api.SonarRuntime;
import org.sonar.api.batch.ScannerSide;
import org.sonar.api.server.ServerSide;
import org.sonar.core.extension.CoreExtension;
import org.sonar.core.extension.CoreExtensionRepository;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
NoAnnotationClass.class, OtherAnnotationClass.class, MultipleAnnotationClass.class);
}
}));
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
- assertThat(container.getPicoContainer().getComponentAdapters())
- .hasSize(ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
- assertThat(container.getComponentByType(CeClass.class)).isNotNull();
- assertThat(container.getComponentByType(MultipleAnnotationClass.class)).isNotNull();
+ assertThat(container.getAddedObjects())
+ .hasSize(2)
+ .contains(CeClass.class, MultipleAnnotationClass.class);
}
@ComputeEngineSide
public class CeTaskInterrupterProviderTest {
- private MapSettings settings = new MapSettings();
- private CeWorkerController ceWorkerController = mock(CeWorkerController.class);
- private System2 system2 = mock(System2.class);
- private CeTaskInterrupterProvider underTest = new CeTaskInterrupterProvider();
+ private final MapSettings settings = new MapSettings();
+ private final CeWorkerController ceWorkerController = mock(CeWorkerController.class);
+ private final System2 system2 = mock(System2.class);
+ private final CeTaskInterrupterProvider underTest = new CeTaskInterrupterProvider();
@Test
public void provide_returns_a_SimpleCeTaskInterrupter_instance_if_configuration_is_empty() {
.isInstanceOf(SimpleCeTaskInterrupter.class);
}
- @Test
- public void provide_always_return_the_same_SimpleCeTaskInterrupter_instance() {
- CeTaskInterrupter instance = underTest.provide(settings.asConfig(), ceWorkerController, system2);
-
- assertThat(instance)
- .isSameAs(underTest.provide(settings.asConfig(), ceWorkerController, system2))
- .isSameAs(underTest.provide(new MapSettings().asConfig(), ceWorkerController, system2));
- }
-
@Test
public void provide_returns_a_TimeoutCeTaskInterrupter_instance_if_property_taskTimeout_has_a_value() throws IllegalAccessException, NoSuchFieldException {
int timeout = 1 + new Random().nextInt(2222);
.hasMessage("The property 'sonar.ce.task.timeoutSeconds' must be a long value >= 1. Got '" + negativeValue + "'");
}
- @Test
- public void provide_always_return_the_same_TimeoutCeTaskInterrupter_instance() {
- int timeout = 1 + new Random().nextInt(2222);
- settings.setProperty("sonar.ce.task.timeoutSeconds", timeout);
-
- CeTaskInterrupter instance = underTest.provide(settings.asConfig(), ceWorkerController, system2);
-
- assertThat(instance)
- .isSameAs(underTest.provide(settings.asConfig(), ceWorkerController, system2))
- .isSameAs(underTest.provide(new MapSettings().setProperty("sonar.ce.task.timeoutSeconds", 999).asConfig(), ceWorkerController, system2));
- }
-
private static Object readField(CeTaskInterrupter instance, String fieldName) throws NoSuchFieldException, IllegalAccessException {
Class<?> clazz = instance.getClass();
Field timeoutField = clazz.getDeclaredField(fieldName);
package org.sonar.ce.taskprocessor;
import org.junit.Test;
-import org.picocontainer.ComponentAdapter;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import org.sonar.ce.notification.ReportAnalysisFailureNotificationExecutionListener;
-import org.sonar.ce.task.CeTaskInterrupter;
-import org.sonar.core.platform.ComponentContainer;
-
-import static org.assertj.core.api.Assertions.assertThat;
+import org.sonar.core.platform.ExtensionContainer;
public class CeTaskProcessorModuleTest {
private CeTaskProcessorModule underTest = new CeTaskProcessorModule();
@Test
- public void defines_CeWorker_ExecutionListener_for_CeLogging() {
- ComponentContainer container = new ComponentContainer();
+ public void defines_module() {
+ var container = mock(ExtensionContainer.class);
underTest.configure(container);
- assertThat(container.getPicoContainer().getComponentAdapters(CeWorker.ExecutionListener.class)
- .stream()
- .map(ComponentAdapter::getComponentImplementation))
- .contains(CeLoggingWorkerExecutionListener.class);
- }
-
- @Test
- public void defines_ExecutionListener_for_report_processing_failure_notifications() {
- ComponentContainer container = new ComponentContainer();
-
- underTest.configure(container);
+ verify(container).add(CeTaskProcessorRepositoryImpl.class);
+ verify(container).add(CeLoggingWorkerExecutionListener.class);
+ verify(container).add(ReportAnalysisFailureNotificationExecutionListener.class);
+ verify(container).add(any(CeTaskInterrupterProvider.class));
+ verify(container).add(CeTaskInterrupterWorkerExecutionListener.class);
+ verify(container).add(CeWorkerFactoryImpl.class);
+ verify(container).add(CeWorkerControllerImpl.class);
+ verify(container).add(CeProcessingSchedulerExecutorServiceImpl.class);
+ verify(container).add(CeProcessingSchedulerImpl.class);
- assertThat(container.getPicoContainer().getComponentAdapters(CeWorker.ExecutionListener.class)
- .stream()
- .map(ComponentAdapter::getComponentImplementation))
- .contains(ReportAnalysisFailureNotificationExecutionListener.class);
- }
-
- @Test
- public void defines_CeTaskInterrupterProvider_object() {
- ComponentContainer container = new ComponentContainer();
-
- underTest.configure(container);
- assertThat(container.getPicoContainer().getComponentAdapter(CeTaskInterrupter.class))
- .isInstanceOf(CeTaskInterrupterProvider.class);
}
}
compile 'commons-lang:commons-lang'
compile 'org.apache.commons:commons-dbcp2'
compile 'org.mybatis:mybatis'
- compile 'org.picocontainer:picocontainer'
compile 'org.slf4j:slf4j-api'
compile project(':server:sonar-process')
compile project(path: ':sonar-plugin-api', configuration: 'shadow')
package org.sonar.db;
import javax.sql.DataSource;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.db.dialect.Dialect;
/**
import org.sonar.db.user.UserTokenMapper;
import org.sonar.db.webhook.WebhookDeliveryMapper;
import org.sonar.db.webhook.WebhookMapper;
+import org.springframework.beans.factory.annotation.Autowired;
public class MyBatis implements Startable {
private final List<MyBatisConfExtension> confExtensions;
private final Database database;
private SqlSessionFactory sessionFactory;
+ @Autowired(required = false)
public MyBatis(Database database) {
this(database, null);
}
+ @Autowired(required = false)
public MyBatis(Database database, @Nullable MyBatisConfExtension[] confExtensions) {
this.confExtensions = confExtensions == null ? Collections.emptyList() : Arrays.asList(confExtensions);
this.database = database;
*/
package org.sonar.db.audit;
+import javax.annotation.Priority;
import org.sonar.db.DbSession;
import org.sonar.db.audit.model.ComponentKeyNewValue;
import org.sonar.db.audit.model.ComponentNewValue;
import org.sonar.db.audit.model.UserTokenNewValue;
import org.sonar.db.audit.model.WebhookNewValue;
+@Priority(2)
public class NoOpAuditPersister implements AuditPersister {
@Override
public void addUserGroup(DbSession dbSession, UserGroupNewValue newValue) {
private static final Optional<String> OPTIONAL_OF_EMPTY_STRING = Optional.of("");
private final System2 system2;
- private AuditPersister auditPersister;
-
- public InternalPropertiesDao(System2 system2) {
- this.system2 = system2;
- }
+ private final AuditPersister auditPersister;
public InternalPropertiesDao(System2 system2, AuditPersister auditPersister) {
this.system2 = system2;
mapper.insertAsText(key, value, now);
}
- if (auditPersister != null && auditPersister.isTrackedProperty(key)) {
+ if (auditPersister.isTrackedProperty(key)) {
if (deletedRows > 0) {
auditPersister.updateProperty(dbSession, new PropertyNewValue(key, value), false);
} else {
int deletedRows = mapper.deleteByKey(key);
mapper.insertAsEmpty(key, system2.now());
- if (auditPersister != null && auditPersister.isTrackedProperty(key)) {
+ if (auditPersister.isTrackedProperty(key)) {
if (deletedRows > 0) {
auditPersister.updateProperty(dbSession, new PropertyNewValue(key, ""), false);
} else {
public void delete(DbSession dbSession, String key) {
int deletedRows = getMapper(dbSession).deleteByKey(key);
- if (auditPersister != null && deletedRows > 0 && auditPersister.isTrackedProperty(key)) {
+ if (deletedRows > 0 && auditPersister.isTrackedProperty(key)) {
auditPersister.deleteProperty(dbSession, new PropertyNewValue(key), false);
}
}
package org.sonar.db;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class DaoModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new DaoModule().configure(container);
- assertThat(container.size()).isGreaterThan(1);
+ assertThat(container.getAddedObjects()).hasSizeGreaterThan(1);
}
}
import org.apache.ibatis.session.Configuration;
import org.hamcrest.core.Is;
-import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
private MyBatis underTest = new MyBatis(database);
- @After
- public void tearDown() {
- underTest.stop();
- }
-
@Test
public void shouldConfigureMyBatis() {
underTest.start();
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.apache.commons.dbcp2.BasicDataSource;
-import org.picocontainer.containers.TransientPicoContainer;
import org.sonar.api.utils.System2;
import org.sonar.core.util.SequenceUuidFactory;
import org.sonar.core.util.UuidFactory;
}
private void initDbClient() {
- TransientPicoContainer ioc = new TransientPicoContainer();
- ioc.addComponent(auditPersister);
- ioc.addComponent(db.getMyBatis());
- ioc.addComponent(system2);
- ioc.addComponent(uuidFactory);
- for (Class daoClass : DaoModule.classes()) {
- ioc.addComponent(daoClass);
+ FastSpringContainer ioc = new FastSpringContainer();
+ ioc.add(auditPersister);
+ ioc.add(db.getMyBatis());
+ ioc.add(system2);
+ ioc.add(uuidFactory);
+ for (Class<?> daoClass : DaoModule.classes()) {
+ ioc.add(daoClass);
}
- List<Dao> daos = ioc.getComponents(Dao.class);
+ ioc.start();
+ List<Dao> daos = ioc.getComponentsByType(Dao.class);
client = new DbClient(db.getDatabase(), db.getMyBatis(), new TestDBSessions(db.getMyBatis()), daos.toArray(new Dao[daos.size()]));
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Supplier;
+import org.sonar.core.platform.Container;
+import org.sonar.core.platform.StartableBeanPostProcessor;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
+import org.springframework.context.support.GenericApplicationContext;
+
+/**
+ * A fast(er) Spring container. It doesn't support several things that are supported in
+ * {@link org.sonar.core.platform.SpringComponentContainer}, such as:
+ * <ul>
+ * <li>Adding extensions</li>
+ * <li>Use of annotations</li>
+ * <li>Adding duplicate components from different Classloaders</li>
+ * <li>Hierarchy of container</li>
+ * <li>Different initialization strategies</li>
+ * </ul>
+ */
+public class FastSpringContainer implements Container {
+ private final GenericApplicationContext context = new GenericApplicationContext();
+
+ public FastSpringContainer() {
+ ((AbstractAutowireCapableBeanFactory) context.getBeanFactory()).setParameterNameDiscoverer(null);
+ add(StartableBeanPostProcessor.class);
+ }
+
+ @Override
+ public Container add(Object... objects) {
+ for (Object o : objects) {
+ if (o instanceof Class) {
+ Class<?> clazz = (Class<?>) o;
+ context.registerBean(clazz.getName(), clazz);
+ } else {
+ registerInstance(o);
+ }
+ }
+ return this;
+ }
+
+ public void start() {
+ context.refresh();
+ }
+
+ private <T> void registerInstance(T instance) {
+ Supplier<T> supplier = () -> instance;
+ Class<T> clazz = (Class<T>) instance.getClass();
+ context.registerBean(clazz.getName(), clazz, supplier);
+ }
+
+ @Override
+ public <T> T getComponentByType(Class<T> type) {
+ try {
+ return context.getBean(type);
+ } catch (Exception t) {
+ throw new IllegalStateException("Unable to load component " + type, t);
+ }
+ }
+
+ @Override public <T> Optional<T> getOptionalComponentByType(Class<T> type) {
+ try {
+ return Optional.of(context.getBean(type));
+ } catch (NoSuchBeanDefinitionException t) {
+ return Optional.empty();
+ }
+ }
+
+ @Override
+ public <T> List<T> getComponentsByType(Class<T> type) {
+ try {
+ return new ArrayList<>(context.getBeansOfType(type).values());
+ } catch (Exception t) {
+ throw new IllegalStateException("Unable to load components " + type, t);
+ }
+ }
+
+ @Override
+ public Container getParent() {
+ return null;
+ }
+}
import org.sonar.api.utils.System2;
import org.sonar.api.utils.Version;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.Container;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.core.util.UuidFactoryFast;
import org.sonar.core.util.logs.Profiler;
import org.sonar.db.dialect.Dialect;
import org.sonar.server.platform.db.migration.MigrationConfigurationModule;
import org.sonar.server.platform.db.migration.engine.MigrationContainer;
import org.sonar.server.platform.db.migration.engine.MigrationContainerImpl;
-import org.sonar.server.platform.db.migration.engine.MigrationContainerPopulator;
-import org.sonar.server.platform.db.migration.engine.MigrationContainerPopulatorImpl;
import org.sonar.server.platform.db.migration.history.MigrationHistoryTableImpl;
import org.sonar.server.platform.db.migration.step.MigrationStep;
import org.sonar.server.platform.db.migration.step.MigrationStepExecutionException;
import org.sonar.server.platform.db.migration.step.MigrationSteps;
import org.sonar.server.platform.db.migration.step.MigrationStepsExecutor;
import org.sonar.server.platform.db.migration.step.RegisteredMigrationStep;
-import org.sonar.server.platform.db.migration.version.DbVersion;
import static com.google.common.base.Preconditions.checkState;
}
}
- public static final class H2MigrationContainerPopulator extends MigrationContainerPopulatorImpl {
- public H2MigrationContainerPopulator(DbVersion... dbVersions) {
- super(H2StepExecutor.class, dbVersions);
- }
- }
-
public static final class H2StepExecutor implements MigrationStepsExecutor {
private static final String STEP_START_PATTERN = "{}...";
private static final String STEP_STOP_PATTERN = "{}: {}";
- private final ComponentContainer componentContainer;
+ private final Container container;
- public H2StepExecutor(ComponentContainer componentContainer) {
- this.componentContainer = componentContainer;
+ public H2StepExecutor(Container container) {
+ this.container = container;
}
@Override
public void execute(List<RegisteredMigrationStep> steps) {
- steps.forEach(step -> execute(step, componentContainer));
+ steps.forEach(step -> execute(step, container));
}
- private void execute(RegisteredMigrationStep step, ComponentContainer componentContainer) {
- MigrationStep migrationStep = componentContainer.getComponentByType(step.getStepClass());
+ private void execute(RegisteredMigrationStep step, Container container) {
+ MigrationStep migrationStep = container.getComponentByType(step.getStepClass());
checkState(migrationStep != null, "Can not find instance of " + step.getStepClass());
execute(step, migrationStep);
}
private void executeDbMigrations(NoopDatabase noopDatabase) {
- ComponentContainer parentContainer = new ComponentContainer();
- parentContainer.add(noopDatabase);
- parentContainer.add(H2MigrationContainerPopulator.class);
+ SpringComponentContainer container = new SpringComponentContainer();
+ container.add(noopDatabase);
MigrationConfigurationModule migrationConfigurationModule = new MigrationConfigurationModule();
- migrationConfigurationModule.configure(parentContainer);
+ migrationConfigurationModule.configure(container);
// dependencies required by DB migrations
- parentContainer.add(SonarRuntimeImpl.forSonarQube(Version.create(8, 0), SonarQubeSide.SERVER, SonarEdition.COMMUNITY));
- parentContainer.add(UuidFactoryFast.getInstance());
- parentContainer.add(System2.INSTANCE);
- parentContainer.add(MapSettings.class);
+ container.add(SonarRuntimeImpl.forSonarQube(Version.create(8, 0), SonarQubeSide.SERVER, SonarEdition.COMMUNITY));
+ container.add(UuidFactoryFast.getInstance());
+ container.add(System2.INSTANCE);
+ container.add(MapSettings.class);
- parentContainer.startComponents();
-
- MigrationContainer migrationContainer = new MigrationContainerImpl(parentContainer, parentContainer.getComponentByType(MigrationContainerPopulator.class));
+ container.startComponents();
+ MigrationContainer migrationContainer = new MigrationContainerImpl(container, H2StepExecutor.class);
MigrationSteps migrationSteps = migrationContainer.getComponentByType(MigrationSteps.class);
- migrationContainer.getComponentByType(MigrationStepsExecutor.class)
- .execute(migrationSteps.readAll());
+ MigrationStepsExecutor executor = migrationContainer.getComponentByType(MigrationStepsExecutor.class);
+
+ executor.execute(migrationSteps.readAll());
}
private void createMigrationHistoryTable(NoopDatabase noopDatabase) {
compile 'commons-lang:commons-lang'
compile 'commons-codec:commons-codec'
compile 'com.fasterxml.staxmate:staxmate'
- compile 'org.picocontainer:picocontainer'
compile project(':server:sonar-db-core')
compile project(':server:sonar-process')
* <p>
* Migration can not be started twice but calling this method wont raise an error.
* </p>
- * <p>
- * <strong>This method should be named {@code start} but it can not be because it will be called by the pico container
- * and this will cause unwanted behavior</strong>
- * </p>
*/
void startIt();
import org.sonar.core.platform.Module;
import org.sonar.server.platform.db.migration.history.MigrationHistoryImpl;
import org.sonar.server.platform.db.migration.history.MigrationHistoryMeddler;
+import org.sonar.server.platform.db.migration.history.MigrationHistoryTableImpl;
import org.sonar.server.platform.db.migration.sql.DbPrimaryKeyConstraintFinder;
import org.sonar.server.platform.db.migration.sql.DropPrimaryKeySqlGenerator;
import org.sonar.server.platform.db.migration.step.MigrationStepRegistryImpl;
@Override
protected void configureModule() {
add(
+ MigrationHistoryTableImpl.class,
// DbVersion implementations
DbVersion00.class,
DbVersion90.class,
package org.sonar.server.platform.db.migration;
import org.sonar.core.platform.Module;
-import org.sonar.server.platform.db.migration.engine.MigrationContainerPopulatorImpl;
import org.sonar.server.platform.db.migration.engine.MigrationEngineImpl;
+import org.sonar.server.platform.db.migration.step.MigrationStepsExecutorImpl;
/**
* Defines the components for the migration engine.
@Override
protected void configureModule() {
add(
- MigrationContainerPopulatorImpl.class,
+ MigrationStepsExecutorImpl.class,
MigrationEngineImpl.class);
}
}
import java.sql.Connection;
import java.sql.SQLException;
import javax.annotation.CheckForNull;
+import javax.inject.Inject;
+
import org.sonar.db.Database;
import org.sonar.db.dialect.Dialect;
import org.sonar.db.dialect.H2;
private final Database db;
private final SqlExecutor sqlExecutor;
+ @Inject
public DatabaseCharsetChecker(Database db) {
this(db, new SqlExecutor());
}
*/
package org.sonar.server.platform.db.migration.engine;
-import org.picocontainer.ComponentAdapter;
-import org.picocontainer.DefaultPicoContainer;
-import org.picocontainer.LifecycleStrategy;
-import org.picocontainer.MutablePicoContainer;
-import org.picocontainer.behaviors.OptInCaching;
-import org.picocontainer.monitors.NullComponentMonitor;
+import java.util.HashSet;
+import java.util.Set;
import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.core.platform.ComponentContainer;
-import org.sonar.core.platform.StartableCloseableSafeLifecyleStrategy;
+import org.sonar.core.platform.LazyStrategy;
+import org.sonar.core.platform.SpringComponentContainer;
+import org.sonar.server.platform.db.migration.step.MigrationStep;
+import org.sonar.server.platform.db.migration.step.MigrationSteps;
+import org.sonar.server.platform.db.migration.step.MigrationStepsExecutor;
-import static java.util.Objects.requireNonNull;
+import static java.util.Collections.emptyList;
-public class MigrationContainerImpl extends ComponentContainer implements MigrationContainer {
+public class MigrationContainerImpl extends SpringComponentContainer implements MigrationContainer {
- public MigrationContainerImpl(ComponentContainer parent, MigrationContainerPopulator populator) {
- super(createContainer(requireNonNull(parent)), parent.getComponentByType(PropertyDefinitions.class));
-
- populateContainer(requireNonNull(populator));
+ public MigrationContainerImpl(SpringComponentContainer parent, Class<? extends MigrationStepsExecutor> executor) {
+ super(parent, parent.getComponentByType(PropertyDefinitions.class), emptyList(), new LazyStrategy());
+ add(executor);
+ addSteps(parent.getComponentByType(MigrationSteps.class));
startComponents();
}
- private void populateContainer(MigrationContainerPopulator populator) {
- populator.populateContainer(this);
- }
-
- /**
- * Creates a PicContainer which extends the specified ComponentContainer <strong>but is not referenced in return</strong>.
- */
- private static MutablePicoContainer createContainer(ComponentContainer parent) {
- LifecycleStrategy lifecycleStrategy = new StartableCloseableSafeLifecyleStrategy() {
- @Override
- public boolean isLazy(ComponentAdapter<?> adapter) {
- return true;
+ private void addSteps(MigrationSteps migrationSteps) {
+ Set<Class<? extends MigrationStep>> classes = new HashSet<>();
+ migrationSteps.readAll().forEach(step -> {
+ Class<? extends MigrationStep> stepClass = step.getStepClass();
+ if (!classes.contains(stepClass)) {
+ add(stepClass);
+ classes.add(stepClass);
}
- };
- return new DefaultPicoContainer(new OptInCaching(), lifecycleStrategy, parent.getPicoContainer(), new NullComponentMonitor());
+ });
}
@Override
* Responsible for:
* <ul>
* <li>adding all the {@link MigrationStep} classes to the container after building it</li>
- * <li>adding dependencies for them to the container if there aren't already available in parent container
- * (see {@link DbVersion#getSupportComponents()})</li>
* <li>adding the {@link MigrationStepsExecutorImpl} to the container</li>
* </ul>
*/
public class MigrationContainerPopulatorImpl implements MigrationContainerPopulator {
- private final DbVersion[] dbVersions;
private final Class<? extends MigrationStepsExecutor> executorType;
- public MigrationContainerPopulatorImpl(DbVersion... dbVersions) {
- this(MigrationStepsExecutorImpl.class, dbVersions);
+ public MigrationContainerPopulatorImpl() {
+ this(MigrationStepsExecutorImpl.class);
}
- protected MigrationContainerPopulatorImpl(Class<? extends MigrationStepsExecutor> executorType, DbVersion... dbVersions) {
- this.dbVersions = dbVersions;
+ protected MigrationContainerPopulatorImpl(Class<? extends MigrationStepsExecutor> executorType) {
this.executorType = executorType;
}
@Override
public void populateContainer(MigrationContainer container) {
container.add(executorType);
- populateFromDbVersion(container);
populateFromMigrationSteps(container);
}
- private void populateFromDbVersion(MigrationContainer container) {
- Arrays.stream(dbVersions)
- .flatMap(DbVersion::getSupportComponents)
- .forEach(container::add);
- }
-
private static void populateFromMigrationSteps(MigrationContainer container) {
MigrationSteps migrationSteps = container.getComponentByType(MigrationSteps.class);
Set<Class<? extends MigrationStep>> classes = new HashSet<>();
import java.util.Optional;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.AnnotationUtils;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.process.ProcessProperties;
import org.sonar.server.platform.db.migration.SupportsBlueGreen;
import org.sonar.server.platform.db.migration.history.MigrationHistory;
import org.sonar.server.platform.db.migration.step.MigrationSteps;
import org.sonar.server.platform.db.migration.step.MigrationStepsExecutor;
+import org.sonar.server.platform.db.migration.step.MigrationStepsExecutorImpl;
import org.sonar.server.platform.db.migration.step.RegisteredMigrationStep;
import static java.lang.String.format;
public class MigrationEngineImpl implements MigrationEngine {
private final MigrationHistory migrationHistory;
- private final ComponentContainer serverContainer;
- private final MigrationContainerPopulator populator;
+ private final SpringComponentContainer serverContainer;
private final MigrationSteps migrationSteps;
private final Configuration configuration;
- public MigrationEngineImpl(MigrationHistory migrationHistory, ComponentContainer serverContainer,
- MigrationContainerPopulator populator, MigrationSteps migrationSteps, Configuration configuration) {
+ public MigrationEngineImpl(MigrationHistory migrationHistory, SpringComponentContainer serverContainer, MigrationSteps migrationSteps, Configuration configuration) {
this.migrationHistory = migrationHistory;
this.serverContainer = serverContainer;
- this.populator = populator;
this.migrationSteps = migrationSteps;
this.configuration = configuration;
}
@Override
public void execute() {
- MigrationContainer migrationContainer = new MigrationContainerImpl(serverContainer, populator);
+ MigrationContainer migrationContainer = new MigrationContainerImpl(serverContainer, MigrationStepsExecutorImpl.class);
boolean blueGreen = configuration.getBoolean(ProcessProperties.Property.BLUE_GREEN_ENABLED.getKey()).orElse(false);
try {
MigrationStepsExecutor stepsExecutor = migrationContainer.getComponentByType(MigrationStepsExecutor.class);
import java.util.List;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.core.platform.Container;
import org.sonar.core.util.logs.Profiler;
-import org.sonar.server.platform.db.migration.engine.MigrationContainer;
import org.sonar.server.platform.db.migration.history.MigrationHistory;
import static com.google.common.base.Preconditions.checkState;
private static final String STEP_START_PATTERN = "{}...";
private static final String STEP_STOP_PATTERN = "{}: {}";
- private final MigrationContainer migrationContainer;
+ private final Container migrationContainer;
private final MigrationHistory migrationHistory;
- public MigrationStepsExecutorImpl(MigrationContainer migrationContainer, MigrationHistory migrationHistory) {
+ public MigrationStepsExecutorImpl(Container migrationContainer, MigrationHistory migrationHistory) {
this.migrationContainer = migrationContainer;
this.migrationHistory = migrationHistory;
}
package org.sonar.server.platform.db.migration.step;
import java.util.Arrays;
-import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.server.platform.db.migration.version.DbVersion;
+import org.springframework.context.annotation.Bean;
/**
* This class is responsible for providing the {@link MigrationSteps} to be injected in classes that need it and
* ensures that there's only one such instance.
*/
-public class MigrationStepsProvider extends ProviderAdapter {
- private MigrationSteps migrationSteps;
-
+public class MigrationStepsProvider {
+ @Bean("MigrationSteps")
public MigrationSteps provide(InternalMigrationStepRegistry migrationStepRegistry, DbVersion... dbVersions) {
- if (migrationSteps == null) {
- migrationSteps = buildMigrationSteps(migrationStepRegistry, dbVersions);
- }
- return migrationSteps;
- }
-
- private static MigrationSteps buildMigrationSteps(InternalMigrationStepRegistry migrationStepRegistry, DbVersion[] dbVersions) {
Arrays.stream(dbVersions).forEach(dbVersion -> dbVersion.addSteps(migrationStepRegistry));
return migrationStepRegistry.build();
}
*/
package org.sonar.server.platform.db.migration.version;
-import java.util.stream.Stream;
import org.sonar.server.platform.db.migration.step.MigrationStepRegistry;
public interface DbVersion {
- /**
- * Components (if any) supporting the {@link org.sonar.server.platform.db.migration.step.MigrationStep} classes
- * added to the registry in {@link #addSteps(MigrationStepRegistry)}.
- * <p>
- * These components will be added to the {@link org.sonar.server.platform.db.migration.engine.MigrationContainer} in
- * which the {@link org.sonar.server.platform.db.migration.step.MigrationStep} classes will be instantiated and run.
- * </p>
- */
- default Stream<Object> getSupportComponents() {
- return Stream.empty();
- }
-
void addSteps(MigrationStepRegistry registry);
}
package org.sonar.server.platform.db.migration;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
@Test
public void verify_component_count() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- assertThat(container.getPicoContainer().getComponentAdapters()).isNotEmpty();
+ assertThat(container.getAddedObjects()).isNotEmpty();
}
}
package org.sonar.server.platform.db.migration;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class MigrationEngineModuleTest {
private MigrationEngineModule underTest = new MigrationEngineModule();
@Test
public void verify_component_count() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- assertThat(container.getPicoContainer().getComponentAdapters())
- .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
+ assertThat(container.getAddedObjects()).hasSize(2);
}
}
*/
package org.sonar.server.platform.db.migration.engine;
+import java.sql.SQLException;
+import java.util.List;
+import org.junit.Before;
import org.junit.Test;
-import org.picocontainer.Startable;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.api.Startable;
+import org.sonar.core.platform.SpringComponentContainer;
+import org.sonar.server.platform.db.migration.step.InternalMigrationStepRegistry;
+import org.sonar.server.platform.db.migration.step.MigrationStep;
+import org.sonar.server.platform.db.migration.step.MigrationStepRegistryImpl;
+import org.sonar.server.platform.db.migration.step.MigrationStepsExecutor;
+import org.sonar.server.platform.db.migration.step.RegisteredMigrationStep;
import static org.assertj.core.api.Assertions.assertThat;
public class MigrationContainerImplTest {
- private ComponentContainer parent = new ComponentContainer();
- private MigrationContainerPopulator populator = container -> container.add(StartCallCounter.class);
-
- private MigrationContainerImpl underTest = new MigrationContainerImpl(parent, populator);
+ private final SpringComponentContainer parent = new SpringComponentContainer();
+ private MigrationContainerImpl underTest;
+
+ @Before
+ public void setUp() {
+ InternalMigrationStepRegistry registry = new MigrationStepRegistryImpl();
+ registry.add(1, "test", NoOpMigrationStep.class);
+
+ parent.add(registry.build());
+ parent.startComponents();
+ underTest = new MigrationContainerImpl(parent, NoOpExecutor.class);
+ underTest.add(StartCallCounter.class);
+ }
@Test
- public void pico_container_of_migration_container_has_pico_container_of_specified_container_as_parent() {
- assertThat(underTest.getPicoContainer().getParent()).isEqualTo(parent.getPicoContainer());
+ public void adds_migration_steps_to_migration_container() {
+ assertThat(underTest.getComponentByType(MigrationStep.class)).isInstanceOf(NoOpMigrationStep.class);
}
@Test
- public void pico_container_of_parent_does_not_have_pico_container_of_migration_container_as_child() {
- assertThat(parent.getPicoContainer().removeChildContainer(underTest.getPicoContainer())).isFalse();
+ public void context_of_migration_container_has_specified_context_as_parent() {
+ assertThat(underTest.context().getParent()).isEqualTo(parent.context());
}
@Test
- public void pico_container_of_migration_container_is_started_in_constructor() {
- assertThat(underTest.getPicoContainer().getLifecycleState().isStarted()).isTrue();
+ public void context_of_migration_container_is_started_in_constructor() {
+ assertThat(underTest.context().isActive()).isTrue();
}
@Test
@Test
public void cleanup_does_not_fail_even_if_stop_of_component_fails() {
- MigrationContainerImpl underTest = new MigrationContainerImpl(parent, (container -> container.add(StopFailing.class)));
+ parent.add(StopFailing.class);
+ MigrationContainerImpl underTest = new MigrationContainerImpl(parent, NoOpExecutor.class);
underTest.cleanup();
}
+ private static class NoOpExecutor implements MigrationStepsExecutor {
+ @Override
+ public void execute(List<RegisteredMigrationStep> steps) {
+
+ }
+ }
+
+ private static class NoOpMigrationStep implements MigrationStep {
+ @Override
+ public void execute() throws SQLException {
+
+ }
+ }
+
public static final class StartCallCounter implements Startable {
private static int startCalls = 0;
*/
package org.sonar.server.platform.db.migration.engine;
-import java.util.stream.Stream;
import org.junit.Before;
import org.junit.Test;
import org.sonar.server.platform.db.migration.history.MigrationHistory;
import org.sonar.server.platform.db.migration.step.MigrationStep;
-import org.sonar.server.platform.db.migration.step.MigrationStepRegistry;
import org.sonar.server.platform.db.migration.step.MigrationSteps;
import org.sonar.server.platform.db.migration.step.MigrationStepsExecutorImpl;
import org.sonar.server.platform.db.migration.step.RegisteredMigrationStep;
-import org.sonar.server.platform.db.migration.version.DbVersion;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static org.mockito.Mockito.when;
public class MigrationContainerPopulatorImplTest {
- private MigrationContainer migrationContainer = new SimpleMigrationContainer();
- private MigrationSteps migrationSteps = mock(MigrationSteps.class);
- private MigrationContainerPopulatorImpl underTest = new MigrationContainerPopulatorImpl();
+ private final SimpleMigrationContainer migrationContainer = new SimpleMigrationContainer();
+ private final MigrationSteps migrationSteps = mock(MigrationSteps.class);
+ private final MigrationContainerPopulatorImpl underTest = new MigrationContainerPopulatorImpl();
@Before
public void setUp() {
migrationContainer.add(migrationSteps);
}
- @Test
- public void populateContainer_adds_components_of_DbVersion_getSupportComponents() {
- MigrationContainerPopulatorImpl underTest = new MigrationContainerPopulatorImpl(
- new NoRegistryDbVersion() {
- @Override
- public Stream<Object> getSupportComponents() {
- return Stream.of(Clazz2.class);
- }
- },
- new NoRegistryDbVersion(),
- new NoRegistryDbVersion() {
- @Override
- public Stream<Object> getSupportComponents() {
- return Stream.of(Clazz1.class, Clazz3.class);
- }
- });
- when(migrationSteps.readAll()).thenReturn(emptyList());
-
- underTest.populateContainer(migrationContainer);
-
- assertThat(migrationContainer.getComponentsByType(Clazz1.class)).isNotNull();
- assertThat(migrationContainer.getComponentsByType(Clazz2.class)).isNotNull();
- assertThat(migrationContainer.getComponentsByType(Clazz3.class)).isNotNull();
- }
-
@Test
public void populateContainer_adds_MigrationStepsExecutorImpl() {
when(migrationSteps.readAll()).thenReturn(emptyList());
// add MigrationStepsExecutorImpl's dependencies
migrationContainer.add(mock(MigrationHistory.class));
+ migrationContainer.startComponents();
underTest.populateContainer(migrationContainer);
assertThat(migrationContainer.getComponentByType(MigrationStepsExecutorImpl.class)).isNotNull();
new RegisteredMigrationStep(2, "bar", MigrationStep2.class),
new RegisteredMigrationStep(3, "dor", MigrationStep3.class)));
+ migrationContainer.startComponents();
underTest.populateContainer(migrationContainer);
assertThat(migrationContainer.getComponentsByType(MigrationStep1.class)).isNotNull();
new RegisteredMigrationStep(4, "foo2", MigrationStep1.class),
new RegisteredMigrationStep(5, "dor", MigrationStep3.class)));
+ migrationContainer.startComponents();
underTest.populateContainer(migrationContainer);
assertThat(migrationContainer.getComponentsByType(MigrationStep1.class)).isNotNull();
public static final class Clazz3 {
}
-
- /**
- * An implementation of DbVersion to be passed to {@link MigrationContainerPopulatorImpl}'s constructor which is
- * not supposed to call the {@link DbVersion#addSteps(MigrationStepRegistry)} method and therefor has an
- * implementation that throws a {@link UnsupportedOperationException} when called.
- */
- private static class NoRegistryDbVersion implements DbVersion {
- @Override
- public void addSteps(MigrationStepRegistry registry) {
- throw new UnsupportedOperationException("addSteps is not supposed to be called");
- }
- }
}
*/
package org.sonar.server.platform.db.migration.engine;
+import java.sql.SQLException;
import java.util.List;
import java.util.Optional;
+import org.junit.Before;
import org.junit.Test;
import org.sonar.api.config.internal.ConfigurationBridge;
import org.sonar.api.config.internal.MapSettings;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.process.ProcessProperties;
import org.sonar.server.platform.db.migration.SupportsBlueGreen;
import org.sonar.server.platform.db.migration.history.MigrationHistory;
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.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
public class MigrationEngineImplTest {
- private MigrationHistory migrationHistory = mock(MigrationHistory.class);
- private ComponentContainer serverContainer = new ComponentContainer();
- private MigrationStepsExecutor stepsExecutor = mock(MigrationStepsExecutor.class);
- private MigrationContainerPopulator populator = container -> container.add(stepsExecutor);
- private MigrationSteps migrationSteps = mock(MigrationSteps.class);
-
- private MapSettings settings = new MapSettings();
- private MigrationEngineImpl underTest = new MigrationEngineImpl(migrationHistory, serverContainer, populator, migrationSteps, new ConfigurationBridge(settings));
+ private final MigrationHistory migrationHistory = mock(MigrationHistory.class);
+ private final SpringComponentContainer serverContainer = new SpringComponentContainer();
+ private final MigrationSteps migrationSteps = mock(MigrationSteps.class);
+ private final StepRegistry stepRegistry = new StepRegistry();
+ private final MapSettings settings = new MapSettings();
+ private final MigrationEngineImpl underTest = new MigrationEngineImpl(migrationHistory, serverContainer, migrationSteps, new ConfigurationBridge(settings));
+
+ @Before
+ public void before() {
+ serverContainer.add(migrationSteps);
+ serverContainer.add(migrationHistory);
+ serverContainer.add(stepRegistry);
+ serverContainer.startComponents();
+ }
@Test
public void execute_execute_all_steps_of_there_is_no_last_migration_number() {
when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.empty());
- List<RegisteredMigrationStep> steps = singletonList(new RegisteredMigrationStep(1, "doo", MigrationStep.class));
+ List<RegisteredMigrationStep> steps = singletonList(new RegisteredMigrationStep(1, "doo", TestMigrationStep.class));
when(migrationSteps.readAll()).thenReturn(steps);
underTest.execute();
- verify(migrationSteps).readAll();
- verify(stepsExecutor).execute(steps);
+ verify(migrationSteps, times(2)).readAll();
+ assertThat(stepRegistry.stepRan).isTrue();
}
@Test
public void execute_execute_steps_from_last_migration_number_plus_1() {
when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.of(50L));
- List<RegisteredMigrationStep> steps = singletonList(new RegisteredMigrationStep(1, "doo", MigrationStep.class));
+ List<RegisteredMigrationStep> steps = singletonList(new RegisteredMigrationStep(1, "doo", TestMigrationStep.class));
when(migrationSteps.readFrom(51)).thenReturn(steps);
+ when(migrationSteps.readAll()).thenReturn(steps);
underTest.execute();
verify(migrationSteps).readFrom(51);
- verify(stepsExecutor).execute(steps);
+ assertThat(stepRegistry.stepRan).isTrue();
}
@Test
when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.of(50L));
List<RegisteredMigrationStep> steps = singletonList(new RegisteredMigrationStep(1, "doo", TestBlueGreenMigrationStep.class));
when(migrationSteps.readFrom(51)).thenReturn(steps);
+ when(migrationSteps.readAll()).thenReturn(steps);
underTest.execute();
verify(migrationSteps).readFrom(51);
- verify(stepsExecutor).execute(steps);
+ assertThat(stepRegistry.stepRan).isTrue();
}
@Test
when(migrationHistory.getLastMigrationNumber()).thenReturn(Optional.of(50L));
List<RegisteredMigrationStep> steps = asList(
new RegisteredMigrationStep(1, "foo", TestBlueGreenMigrationStep.class),
- new RegisteredMigrationStep(2, "bar", MigrationStep.class));
+ new RegisteredMigrationStep(2, "bar", TestMigrationStep.class));
when(migrationSteps.readFrom(51)).thenReturn(steps);
try {
fail();
} catch (IllegalStateException e) {
assertThat(e).hasMessage("All migrations canceled. #2 does not support blue/green deployment: bar");
- verifyZeroInteractions(stepsExecutor);
+ assertThat(stepRegistry.stepRan).isFalse();
+ }
+ }
+
+ private static class NoOpExecutor implements MigrationStepsExecutor {
+ @Override
+ public void execute(List<RegisteredMigrationStep> steps) {
+ // no op
+ }
+ }
+
+ private static class StepRegistry {
+ boolean stepRan = false;
+ }
+
+ private static class TestMigrationStep implements MigrationStep {
+ private final StepRegistry registry;
+
+ public TestMigrationStep(StepRegistry registry) {
+ this.registry = registry;
+ }
+ @Override
+ public void execute() throws SQLException {
+ registry.stepRan = true;
}
}
@SupportsBlueGreen
private static class TestBlueGreenMigrationStep implements MigrationStep {
+ private final StepRegistry registry;
+ public TestBlueGreenMigrationStep(StepRegistry registry) {
+ this.registry = registry;
+ }
@Override
- public void execute() {
-
+ public void execute() throws SQLException {
+ registry.stepRan = true;
}
}
}
*/
package org.sonar.server.platform.db.migration.engine;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
-public final class SimpleMigrationContainer extends ComponentContainer implements MigrationContainer {
+public final class SimpleMigrationContainer extends SpringComponentContainer implements MigrationContainer {
@Override
public void cleanup() {
import org.junit.Test;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.server.platform.db.migration.engine.MigrationContainer;
import org.sonar.server.platform.db.migration.engine.SimpleMigrationContainer;
import org.sonar.server.platform.db.migration.history.MigrationHistory;
public void execute_fails_with_ISE_if_no_instance_of_computation_step_exist_in_container() {
List<RegisteredMigrationStep> steps = asList(registeredStepOf(1, MigrationStep1.class));
+ ((SpringComponentContainer) migrationContainer).startComponents();
try {
underTest.execute(steps);
fail("execute should have thrown a IllegalStateException");
} catch (IllegalStateException e) {
- assertThat(e).hasMessage("Can not find instance of " + MigrationStep1.class);
+ assertThat(e).hasMessage("Unable to load component " + MigrationStep1.class);
} finally {
assertThat(logTester.logs()).hasSize(2);
assertLogLevel(LoggerLevel.INFO, "Executing DB migrations...");
@Test
public void execute_execute_the_instance_of_type_specified_in_step_in_stream_order() {
migrationContainer.add(MigrationStep1.class, MigrationStep2.class, MigrationStep3.class);
+ ((SpringComponentContainer) migrationContainer).startComponents();
underTest.execute(asList(
registeredStepOf(1, MigrationStep2.class),
registeredStepOf(2, SqlExceptionFailingMigrationStep.class),
registeredStepOf(3, MigrationStep3.class));
+ ((SpringComponentContainer) migrationContainer).startComponents();
try {
underTest.execute(steps);
fail("a MigrationStepExecutionException should have been thrown");
registeredStepOf(2, RuntimeExceptionFailingMigrationStep.class),
registeredStepOf(3, MigrationStep3.class));
+ ((SpringComponentContainer) migrationContainer).startComponents();
try {
underTest.execute(steps);
fail("should throw MigrationStepExecutionException");
*/
package org.sonar.server.platform.db.migration.step;
-import java.util.Random;
import org.junit.Test;
import org.mockito.InOrder;
import org.sonar.server.platform.db.migration.version.DbVersion;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
public class MigrationStepsProviderTest {
- private InternalMigrationStepRegistry internalMigrationStepRegistry = mock(InternalMigrationStepRegistry.class);
- private MigrationStepsProvider underTest = new MigrationStepsProvider();
+ private final InternalMigrationStepRegistry internalMigrationStepRegistry = mock(InternalMigrationStepRegistry.class);
+ private final MigrationStepsProvider underTest = new MigrationStepsProvider();
@Test
public void provide_throws_ISE_with_registry_build_throws_ISE_because_it_is_empty() {
}
@Test
- public void provide_calls_DbVersion_addStep_in_order_and_only_once() {
+ public void provide_calls_DbVersion_addStep_in_order() {
DbVersion dbVersion1 = newMockFailingOnSecondBuildCall();
DbVersion dbVersion2 = newMockFailingOnSecondBuildCall();
DbVersion dbVersion3 = newMockFailingOnSecondBuildCall();
inOrder.verify(dbVersion2).addSteps(internalMigrationStepRegistry);
inOrder.verify(dbVersion3).addSteps(internalMigrationStepRegistry);
inOrder.verifyNoMoreInteractions();
-
- // calling a second time with another argument, it's just ignored
- DbVersion dbVersion4 = newMockFailingOnSecondBuildCall();
- assertThat(underTest.provide(internalMigrationStepRegistry, dbVersion4)).isSameAs(expected);
- verifyZeroInteractions(dbVersion4);
- }
-
- @Test
- public void provide_always_returns_the_same_MigrationSteps_instance_and_calls_registry_build_only_once() {
- MigrationSteps migrationSteps = mock(MigrationSteps.class);
- when(internalMigrationStepRegistry.build())
- .thenReturn(migrationSteps)
- .thenThrow(new RuntimeException("method build should not be called twice"));
-
- for (int i = 0; i < Math.abs(new Random().nextInt(50)) + 1; i++) {
- assertThat(underTest.provide(internalMigrationStepRegistry)).isSameAs(migrationSteps);
- }
-
}
private static DbVersion newMockFailingOnSecondBuildCall() {
import org.junit.Test;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationCount;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;
public class DbVersion00Test {
private DbVersion00 underTest = new DbVersion00();
- @Test
- public void verify_no_support_component() {
- assertThat(underTest.getSupportComponents()).isEmpty();
- }
-
@Test
public void migrationNumber_starts_at_1153() {
verifyMinimumMigrationNumber(underTest, 1);
import org.junit.Test;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationCount;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;
private final DbVersion90 underTest = new DbVersion90();
- @Test
- public void verify_no_support_component() {
- assertThat(underTest.getSupportComponents()).isEmpty();
- }
-
@Test
public void migrationNumber_starts_at_5001() {
verifyMinimumMigrationNumber(underTest, 5001);
import org.junit.Test;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationCount;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;
private final DbVersion91 underTest = new DbVersion91();
- @Test
- public void verify_no_support_component() {
- assertThat(underTest.getSupportComponents()).isEmpty();
- }
-
@Test
public void migrationNumber_starts_at_6001() {
verifyMinimumMigrationNumber(underTest, 6001);
import org.junit.Test;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationNotEmpty;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;
private final DbVersion92 underTest = new DbVersion92();
- @Test
- public void verify_no_support_component() {
- assertThat(underTest.getSupportComponents()).isEmpty();
- }
-
@Test
public void migrationNumber_starts_at_6101() {
verifyMinimumMigrationNumber(underTest, 6101);
import org.junit.Test;
-import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationNotEmpty;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;
private final DbVersion93 underTest = new DbVersion93();
- @Test
- public void verify_no_support_component() {
- assertThat(underTest.getSupportComponents()).isEmpty();
- }
-
@Test
public void migrationNumber_starts_at_6101() {
verifyMinimumMigrationNumber(underTest, 6201);
import org.sonar.process.cluster.hz.HazelcastObjects;
import static java.util.Objects.requireNonNull;
+import org.springframework.beans.factory.annotation.Autowired;
public class SharedHealthStateImpl implements SharedHealthState {
private static final Logger LOG = LoggerFactory.getLogger(SharedHealthStateImpl.class);
private final HazelcastMember hzMember;
+ @Autowired(required = false)
public SharedHealthStateImpl(HazelcastMember hzMember) {
this.hzMember = hzMember;
}
+ @Autowired(required = false)
public SharedHealthStateImpl() {
this(null);
}
*/
package org.sonar.server.async;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.process.Jmx;
public class AsyncExecutionMBeanImpl implements AsyncExecutionMBean, Startable {
import static org.sonar.server.es.newindex.SettingsConfiguration.newBuilder;
import static org.sonar.server.permission.index.IndexAuthorizationConstants.TYPE_AUTHORIZATION;
+import javax.inject.Inject;
+
public class ComponentIndexDefinition implements IndexDefinition {
public static final Index DESCRIPTOR = Index.withRelations("components");
this.enableSource = enableSource;
}
+ @Inject
public ComponentIndexDefinition(Configuration config) {
this(config, false);
}
*/
package org.sonar.server.config;
-import java.util.Optional;
-import java.util.function.UnaryOperator;
+import static java.util.function.UnaryOperator.identity;
import org.apache.commons.lang.ArrayUtils;
-import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.config.Configuration;
import org.sonar.api.config.PropertyDefinition;
-import org.sonar.api.config.internal.Settings;
-
-import static java.util.function.UnaryOperator.identity;
import static org.sonar.api.config.internal.MultivalueProperty.parseAsCsv;
+import org.sonar.api.config.internal.Settings;
+import org.springframework.context.annotation.Bean;
-public class ConfigurationProvider extends ProviderAdapter {
+import java.util.Optional;
+import java.util.function.UnaryOperator;
- private Configuration configuration;
+public class ConfigurationProvider {
+ @Bean("Configuration")
public Configuration provide(Settings settings) {
- if (configuration == null) {
- configuration = new ServerConfigurationAdapter(settings);
- }
- return configuration;
+ return new ServerConfigurationAdapter(settings);
}
private static class ServerConfigurationAdapter implements Configuration {
import java.util.stream.Collectors;
import org.apache.http.HttpHost;
import org.elasticsearch.common.settings.Settings;
-import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.config.Configuration;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.process.cluster.NodeType;
+import org.springframework.context.annotation.Bean;
import static org.sonar.process.ProcessProperties.Property.CLUSTER_ENABLED;
import static org.sonar.process.ProcessProperties.Property.CLUSTER_NAME;
@ComputeEngineSide
@ServerSide
-public class EsClientProvider extends ProviderAdapter {
-
+public class EsClientProvider {
private static final Logger LOGGER = Loggers.get(EsClientProvider.class);
- private EsClient cache;
-
+ @Bean("EsClient")
public EsClient provide(Configuration config) {
- if (cache == null) {
- Settings.Builder esSettings = Settings.builder();
+ Settings.Builder esSettings = Settings.builder();
- // mandatory property defined by bootstrap process
- esSettings.put("cluster.name", config.get(CLUSTER_NAME.getKey()).get());
+ // mandatory property defined by bootstrap process
+ esSettings.put("cluster.name", config.get(CLUSTER_NAME.getKey()).get());
- boolean clusterEnabled = config.getBoolean(CLUSTER_ENABLED.getKey()).orElse(false);
- boolean searchNode = !clusterEnabled || SEARCH.equals(NodeType.parse(config.get(CLUSTER_NODE_TYPE.getKey()).orElse(null)));
- List<HttpHost> httpHosts;
- if (clusterEnabled && !searchNode) {
- httpHosts = getHttpHosts(config);
+ boolean clusterEnabled = config.getBoolean(CLUSTER_ENABLED.getKey()).orElse(false);
+ boolean searchNode = !clusterEnabled || SEARCH.equals(NodeType.parse(config.get(CLUSTER_NODE_TYPE.getKey()).orElse(null)));
+ List<HttpHost> httpHosts;
+ if (clusterEnabled && !searchNode) {
+ httpHosts = getHttpHosts(config);
- LOGGER.info("Connected to remote Elasticsearch: [{}]", displayedAddresses(httpHosts));
- } else {
- // defaults provided in:
- // * in org.sonar.process.ProcessProperties.Property.SEARCH_HOST
- // * in org.sonar.process.ProcessProperties.Property.SEARCH_PORT
- HostAndPort host = HostAndPort.fromParts(config.get(SEARCH_HOST.getKey()).get(), config.getInt(SEARCH_PORT.getKey()).get());
- httpHosts = Collections.singletonList(toHttpHost(host));
- LOGGER.info("Connected to local Elasticsearch: [{}]", displayedAddresses(httpHosts));
- }
-
- cache = new EsClient(config.get(CLUSTER_SEARCH_PASSWORD.getKey()).orElse(null), httpHosts.toArray(new HttpHost[0]));
+ LOGGER.info("Connected to remote Elasticsearch: [{}]", displayedAddresses(httpHosts));
+ } else {
+ // defaults provided in:
+ // * in org.sonar.process.ProcessProperties.Property.SEARCH_HOST
+ // * in org.sonar.process.ProcessProperties.Property.SEARCH_PORT
+ HostAndPort host = HostAndPort.fromParts(config.get(SEARCH_HOST.getKey()).get(), config.getInt(SEARCH_PORT.getKey()).get());
+ httpHosts = Collections.singletonList(toHttpHost(host));
+ LOGGER.info("Connected to local Elasticsearch: [{}]", displayedAddresses(httpHosts));
}
- return cache;
+
+ return new EsClient(config.get(CLUSTER_SEARCH_PASSWORD.getKey()).orElse(null), httpHosts.toArray(new HttpHost[0]));
}
private static List<HttpHost> getHttpHosts(Configuration config) {
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.es;
-
-import org.sonar.api.Startable;
-
-/**
- * Workaround of a behaviour of picocontainer: components
- * instantiated by {@link org.picocontainer.injectors.ProviderAdapter}
- * can't have a lifecycle. The methods start() and stop()
- * of {@link Startable} are not executed.
- * The same behaviour exists for the {@link org.picocontainer.injectors.ProviderAdapter}
- * itself.
- *
- * As {@link EsClientStopper} implements {@link Startable}, it can
- * close {@link EsClient} when process shutdowns.
- *
- */
-public class EsClientStopper implements Startable {
-
- private final EsClient esClient;
-
- public EsClientStopper(EsClient esClient) {
- this.esClient = esClient;
- }
-
- @Override
- public void start() {
- // nothing to do
- }
-
- @Override
- public void stop() {
- esClient.close();
- }
-}
@Override
protected void configureModule() {
add(new EsClientProvider());
- add(EsClientStopper.class);
}
}
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import static java.lang.String.format;
public class CoreExtensionBootstraper implements ServerStartHandler {
private static final Logger LOGGER = Loggers.get(CoreExtensionBootstraper.class);
- private final ComponentContainer componentContainer;
+ private final SpringComponentContainer componentContainer;
- public CoreExtensionBootstraper(ComponentContainer componentContainer) {
+ public CoreExtensionBootstraper(SpringComponentContainer componentContainer) {
this.componentContainer = componentContainer;
}
*/
package org.sonar.server.extension;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
/**
* Interface implemented by the Extension point exposed by the Core Extensions that serves as the unique access
/**
* Bootstraps the plugin.
*
- * @param parent the parent ComponentContainer which provides Platform components for the Privileged plugin to use.
+ * @param parent the parent SpringComponentContainer which provides Platform components for the Privileged plugin to use.
*
* @throws IllegalStateException if called more than once
*/
- void startPlugin(ComponentContainer parent);
+ void startPlugin(SpringComponentContainer parent);
/**
* This method is called when Platform is shutting down.
package org.sonar.server.extension;
import java.util.List;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.Container;
import static java.lang.String.format;
public class CoreExtensionStopper implements Startable {
private static final Logger LOGGER = Loggers.get(CoreExtensionStopper.class);
- private final ComponentContainer platformContainer;
+ private final Container platformContainer;
- public CoreExtensionStopper(ComponentContainer platformContainer) {
+ public CoreExtensionStopper(Container platformContainer) {
this.platformContainer = platformContainer;
}
import static org.sonar.server.es.newindex.SettingsConfiguration.newBuilder;
import static org.sonar.server.permission.index.IndexAuthorizationConstants.TYPE_AUTHORIZATION;
+import javax.inject.Inject;
+
/**
* Definition of ES index "issues", including settings and fields.
*/
private final Configuration config;
private final boolean enableSource;
+ @Inject
public IssueIndexDefinition(Configuration config) {
this(config, false);
}
package org.sonar.server.issue.workflow;
import java.util.List;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.issue.DefaultTransitions;
import org.sonar.api.issue.Issue;
import ch.qos.logback.classic.Logger;
import com.google.common.annotations.VisibleForTesting;
import java.io.File;
-import org.picocontainer.Startable;
+import javax.inject.Inject;
+import org.sonar.api.Startable;
import org.slf4j.LoggerFactory;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.config.Configuration;
private final ServerProcessLogging serverProcessLogging;
private final Database database;
+ @Inject
public ServerLogging(Configuration config, ServerProcessLogging serverProcessLogging, Database database) {
this(new LogbackHelper(), config, serverProcessLogging, database);
}
import static org.sonar.server.es.newindex.SettingsConfiguration.MANUAL_REFRESH_INTERVAL;
import static org.sonar.server.es.newindex.SettingsConfiguration.newBuilder;
+import javax.inject.Inject;
+
public class ProjectMeasuresIndexDefinition implements IndexDefinition {
public static final Index DESCRIPTOR = Index.withRelations("projectmeasures");
this.enableSource = enableSource;
}
+ @Inject
public ProjectMeasuresIndexDefinition(Configuration config) {
this(config, false);
}
private static final String UNABLE_TO_READ_NOTIFICATION = "Unable to read notification";
- private NotificationChannel[] notificationChannels;
+ private final NotificationChannel[] notificationChannels;
private final DbClient dbClient;
private boolean alreadyLoggedDeserializationIssue = false;
- /**
- * Default constructor used by Pico
- */
public DefaultNotificationManager(NotificationChannel[] channels, DbClient dbClient) {
this.notificationChannels = channels;
this.dbClient = dbClient;
/**
* The notification manager receives notifications and is in charge of storing them so that they are processed by the notification service.
* <p>
- * Pico provides an instance of this class, and plugins just need to create notifications and pass them to this manager with
+ * The ioc container provides an instance of this class, and plugins just need to create notifications and pass them to this manager with
* the {@link NotificationManager#scheduleForSending(Notification)} method.
* </p>
*/
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
+import org.springframework.beans.factory.annotation.Autowired;
import static com.google.common.base.Preconditions.checkArgument;
private final List<NotificationHandler<? extends Notification>> handlers;
private final DbClient dbClient;
+ @Autowired(required = false)
public NotificationService(DbClient dbClient, NotificationDispatcher[] dispatchers, NotificationHandler<? extends Notification>[] handlers) {
this.dbClient = dbClient;
this.dispatchers = ImmutableList.copyOf(dispatchers);
}
/**
- * Used by Pico when there are no handler nor dispatcher.
+ * Used by the ioc container when there are no handler nor dispatcher.
*/
+ @Autowired(required = false)
public NotificationService(DbClient dbClient) {
this(dbClient, new NotificationDispatcher[0], new NotificationHandler[0]);
}
/**
- * Used by Pico when there are no dispatcher.
+ * Used by the ioc container when there are no dispatcher.
*/
+ @Autowired(required = false)
public NotificationService(DbClient dbClient, NotificationHandler[] handlers) {
this(dbClient, new NotificationDispatcher[0], handlers);
}
/**
- * Used by Pico when there are no handler.
+ * Used by the ioc container when there are no handler.
*/
+ @Autowired(required = false)
public NotificationService(DbClient dbClient, NotificationDispatcher[] dispatchers) {
this(dbClient, dispatchers, new NotificationHandler[0]);
}
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
*/
package org.sonar.server.platform;
-import org.picocontainer.Startable;
-import org.sonar.api.utils.log.Loggers;
+import javax.annotation.Nullable;
+import org.sonar.api.Startable;
import org.sonar.api.platform.Server;
import org.sonar.api.platform.ServerStartHandler;
import org.sonar.api.platform.ServerStopHandler;
+import org.sonar.api.utils.log.Loggers;
/**
* @since 2.2
*/
public class ServerLifecycleNotifier implements Startable {
- private ServerStartHandler[] startHandlers;
- private ServerStopHandler[] stopHandlers;
- private Server server;
+ private final ServerStartHandler[] startHandlers;
+ private final ServerStopHandler[] stopHandlers;
+ private final Server server;
- public ServerLifecycleNotifier(Server server, ServerStartHandler[] startHandlers, ServerStopHandler[] stopHandlers) {
- this.startHandlers = startHandlers;
- this.stopHandlers = stopHandlers;
+ public ServerLifecycleNotifier(Server server, @Nullable ServerStartHandler[] startHandlers, @Nullable ServerStopHandler[] stopHandlers) {
+ this.startHandlers = startHandlers != null ? startHandlers : new ServerStartHandler[0];
+ this.stopHandlers = stopHandlers != null ? stopHandlers: new ServerStopHandler[0];
this.server = server;
}
- public ServerLifecycleNotifier(Server server, ServerStartHandler[] startHandlers) {
- this(server, startHandlers, new ServerStopHandler[0]);
- }
-
- public ServerLifecycleNotifier(Server server, ServerStopHandler[] stopHandlers) {
- this(server, new ServerStartHandler[0], stopHandlers);
- }
-
- public ServerLifecycleNotifier(Server server) {
- this(server, new ServerStartHandler[0], new ServerStopHandler[0]);
- }
-
@Override
public void start() {
/* IMPORTANT :
we want to be sure that handlers are notified when all other services are started.
- That's why the class Platform explicitely executes the method notifyStart(), instead of letting picocontainer
+ That's why the class Platform explicitely executes the method notifyStart(), instead of letting the ioc container
choose the startup order.
*/
}
*/
package org.sonar.server.platform;
-import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.CoreProperties;
import org.sonar.api.SonarQubeSide;
import org.sonar.api.SonarRuntime;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.property.PropertyDto;
+import org.springframework.context.annotation.Bean;
import static com.google.common.base.Preconditions.checkState;
import static org.apache.commons.lang.StringUtils.isBlank;
@ComputeEngineSide
@ServerSide
-public class StartupMetadataProvider extends ProviderAdapter {
-
- private StartupMetadata cache = null;
-
+public class StartupMetadataProvider {
+ @Bean("StartupMetadata")
public StartupMetadata provide(System2 system, SonarRuntime runtime, WebServer webServer, DbClient dbClient) {
- if (cache == null) {
- if (runtime.getSonarQubeSide() == SonarQubeSide.SERVER && webServer.isStartupLeader()) {
- cache = generate(system);
- } else {
- cache = load(dbClient);
- }
+ if (runtime.getSonarQubeSide() == SonarQubeSide.SERVER && webServer.isStartupLeader()) {
+ return generate(system);
+ } else {
+ return load(dbClient);
}
- return cache;
}
/**
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
-import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.impl.utils.DefaultTempFolder;
import org.sonar.api.utils.TempFolder;
+import org.springframework.context.annotation.Bean;
-public class TempFolderProvider extends ProviderAdapter {
-
- private TempFolder tempFolder;
-
+public class TempFolderProvider {
+ @Bean("TempFolder")
public TempFolder provide(ServerFileSystem fs) {
- if (tempFolder == null) {
- File tempDir = new File(fs.getTempDir(), "tmp");
- try {
- FileUtils.forceMkdir(tempDir);
- } catch (IOException e) {
- throw new IllegalStateException("Unable to create temp directory " + tempDir, e);
- }
- tempFolder = new DefaultTempFolder(tempDir);
+ File tempDir = new File(fs.getTempDir(), "tmp");
+ try {
+ FileUtils.forceMkdir(tempDir);
+ } catch (IOException e) {
+ throw new IllegalStateException("Unable to create temp directory " + tempDir, e);
}
- return tempFolder;
+ return new DefaultTempFolder(tempDir);
}
}
*/
package org.sonar.server.plugins;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.core.platform.PluginRepository;
import org.sonar.updatecenter.common.PluginReferential;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ListMultimap;
-import java.lang.annotation.Annotation;
-import java.util.Collection;
-import java.util.Set;
import org.sonar.api.Plugin;
import org.sonar.api.SonarRuntime;
import org.sonar.api.config.Configuration;
import org.sonar.api.internal.PluginContextImpl;
import org.sonar.api.utils.AnnotationUtils;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ExtensionContainer;
import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginRepository;
+import java.lang.annotation.Annotation;
+import java.util.Collection;
+import java.util.Set;
+
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
* Loads the plugins server extensions and injects them to DI container
*/
public abstract class ServerExtensionInstaller {
+ private final Configuration configuration;
private final SonarRuntime sonarRuntime;
private final PluginRepository pluginRepository;
private final Set<Class<? extends Annotation>> supportedAnnotationTypes;
- protected ServerExtensionInstaller(SonarRuntime sonarRuntime, PluginRepository pluginRepository, Collection<Class<? extends Annotation>> supportedAnnotationTypes) {
+ protected ServerExtensionInstaller(Configuration configuration, SonarRuntime sonarRuntime, PluginRepository pluginRepository,
+ Collection<Class<? extends Annotation>> supportedAnnotationTypes) {
requireNonNull(supportedAnnotationTypes, "At least one supported annotation type must be specified");
+ this.configuration = configuration;
this.sonarRuntime = sonarRuntime;
this.pluginRepository = pluginRepository;
this.supportedAnnotationTypes = ImmutableSet.copyOf(supportedAnnotationTypes);
}
- public void installExtensions(ComponentContainer container) {
+ public void installExtensions(ExtensionContainer container) {
ListMultimap<PluginInfo, Object> installedExtensionsByPlugin = ArrayListMultimap.create();
for (PluginInfo pluginInfo : pluginRepository.getPluginInfos()) {
try {
Plugin.Context context = new PluginContextImpl.Builder()
.setSonarRuntime(sonarRuntime)
- .setBootConfiguration(container.getComponentByType(Configuration.class))
+ .setBootConfiguration(configuration)
.build();
plugin.define(context);
for (Object extension : context.getExtensions()) {
}
}
- private Object installExtension(ComponentContainer container, PluginInfo pluginInfo, Object extension) {
+ private Object installExtension(ExtensionContainer container, PluginInfo pluginInfo, Object extension) {
for (Class<? extends Annotation> supportedAnnotationType : supportedAnnotationTypes) {
if (AnnotationUtils.getAnnotation(extension, supportedAnnotationType) != null) {
container.addExtension(pluginInfo, extension);
import static org.sonar.server.es.newindex.SettingsConfiguration.MANUAL_REFRESH_INTERVAL;
import static org.sonar.server.es.newindex.SettingsConfiguration.newBuilder;
+import javax.inject.Inject;
+
/**
* Definition of ES index "rules", including settings and fields.
*/
private final Configuration config;
private final boolean enableSource;
+ @Inject
public RuleIndexDefinition(Configuration config) {
this(config, false);
}
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
+import javax.inject.Inject;
import org.apache.ibatis.exceptions.PersistenceException;
import org.sonar.api.CoreProperties;
import org.sonar.api.ce.ComputeEngineSide;
private Map<String, String> getPropertiesDbFailureCache = Collections.emptyMap();
private SettingLoader settingLoader;
+ @Inject
public ThreadLocalSettings(PropertyDefinitions definitions, Properties props) {
this(definitions, props, new NopSettingLoader());
}
package org.sonar.server.util;
import okhttp3.OkHttpClient;
-import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.SonarRuntime;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.config.Configuration;
import org.sonar.api.server.ServerSide;
import org.sonarqube.ws.client.OkHttpClientBuilder;
+import org.springframework.context.annotation.Bean;
import static java.lang.String.format;
import static org.sonar.process.ProcessProperties.Property.HTTP_PROXY_PASSWORD;
*/
@ServerSide
@ComputeEngineSide
-public class OkHttpClientProvider extends ProviderAdapter {
+public class OkHttpClientProvider {
private static final int DEFAULT_CONNECT_TIMEOUT_IN_MS = 10_000;
private static final int DEFAULT_READ_TIMEOUT_IN_MS = 10_000;
- private okhttp3.OkHttpClient okHttpClient;
-
/**
* @return a {@link OkHttpClient} singleton
*/
+ @Bean("OkHttpClient")
public OkHttpClient provide(Configuration config, SonarRuntime runtime) {
- if (okHttpClient == null) {
- OkHttpClientBuilder builder = new OkHttpClientBuilder();
- builder.setConnectTimeoutMs(DEFAULT_CONNECT_TIMEOUT_IN_MS);
- builder.setReadTimeoutMs(DEFAULT_READ_TIMEOUT_IN_MS);
- // no need to define proxy URL as system-wide proxy is used and properly
- // configured by bootstrap process.
- builder.setProxyLogin(config.get(HTTP_PROXY_USER.getKey()).orElse(null));
- builder.setProxyPassword(config.get(HTTP_PROXY_PASSWORD.getKey()).orElse(null));
- builder.setUserAgent(format("SonarQube/%s", runtime.getApiVersion().toString()));
- okHttpClient = builder.build();
- }
- return okHttpClient;
+ OkHttpClientBuilder builder = new OkHttpClientBuilder();
+ builder.setConnectTimeoutMs(DEFAULT_CONNECT_TIMEOUT_IN_MS);
+ builder.setReadTimeoutMs(DEFAULT_READ_TIMEOUT_IN_MS);
+ // no need to define proxy URL as system-wide proxy is used and properly
+ // configured by bootstrap process.
+ builder.setProxyLogin(config.get(HTTP_PROXY_USER.getKey()).orElse(null));
+ builder.setProxyPassword(config.get(HTTP_PROXY_PASSWORD.getKey()).orElse(null));
+ builder.setUserAgent(format("SonarQube/%s", runtime.getApiVersion().toString()));
+ return builder.build();
}
}
package org.sonar.server.util;
import java.util.concurrent.ExecutorService;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
/**
- * ExecutorService that exposes a {@code stop} method which can be invoked by Pico container to shutdown properly
+ * ExecutorService that exposes a {@code stop} method which can be invoked by the ioc container to shutdown properly
* the service.
*/
public interface StoppableExecutorService extends ExecutorService, Startable {
import java.util.concurrent.ScheduledExecutorService;
/**
- * ScheduledExecutorService that exposes a {@code stop} method which can be invoked by Pico container to shutdown
+ * ScheduledExecutorService that exposes a {@code stop} method which can be invoked by the ioc container to shutdown
* properly the service.
*/
public interface StoppableScheduledExecutorService extends ScheduledExecutorService, StoppableExecutorService {
import static org.sonar.process.ProcessProperties.Property.SEARCH_PORT;
public class EsClientProviderTest {
-
-
@Rule
public LogTester logTester = new LogTester();
assertThat(node.getHost().getPort()).isEqualTo(9000);
assertThat(logTester.logs(LoggerLevel.INFO)).has(new Condition<>(s -> s.contains("Connected to local Elasticsearch: [http://" + localhostHostname + ":9000]"), ""));
-
- // keep in cache
- assertThat(underTest.provide(settings.asConfig())).isSameAs(client);
}
@Test
assertThat(logTester.logs(LoggerLevel.INFO))
.has(new Condition<>(s -> s.contains("Connected to remote Elasticsearch: [http://" + localhostHostname + ":8080, http://" + localhostHostname + ":8081]"), ""));
-
- // keep in cache
- assertThat(underTest.provide(settings.asConfig())).isSameAs(client);
}
@Test
assertThat(logTester.logs(LoggerLevel.INFO))
.has(new Condition<>(s -> s.contains("Connected to remote Elasticsearch: [http://" + localhostHostname + ":9001, http://" + localhostHostname + ":8081]"), ""));
-
- // keep in cache
- assertThat(underTest.provide(settings.asConfig())).isSameAs(client);
}
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.es;
-
-import org.junit.Test;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-public class EsClientStopperTest {
-
- private EsClient client = mock(EsClient.class);
- private EsClientStopper underTest = new EsClientStopper(client);
-
- @Test
- public void stop_client() {
- underTest.start();
- verifyNoMoreInteractions(client);
-
- underTest.stop();
- verify(client).close();
- }
-}
package org.sonar.server.es;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class EsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new EsModule().configure(container);
- assertThat(container.size()).isEqualTo(2 + COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER);
+ assertThat(container.getAddedObjects()).hasSize(1);
}
-
}
import org.junit.Test;
import org.sonar.api.platform.Server;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
public class CoreExtensionBootstraperTest {
- private ComponentContainer componentContainer = new ComponentContainer();
- private CoreExtensionBridge bridge = mock(CoreExtensionBridge.class);
-
- private CoreExtensionBootstraper underTest = new CoreExtensionBootstraper(componentContainer);
+ private final SpringComponentContainer componentContainer = new SpringComponentContainer();
+ private final CoreExtensionBridge bridge = mock(CoreExtensionBridge.class);
+ private final CoreExtensionBootstraper underTest = new CoreExtensionBootstraper(componentContainer);
@Test
public void onServerStart_calls_startPlugin_if_Bridge_exists_in_container() {
@Test
public void onServerStart_does_not_call_startPlugin_if_Bridge_does_not_exist_in_container() {
+ componentContainer.startComponents();
underTest.onServerStart(mock(Server.class));
verifyNoMoreInteractions(bridge);
package org.sonar.server.extension;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
public class CoreExtensionStopperTest {
- private ComponentContainer componentContainer = new ComponentContainer();
- private CoreExtensionBridge bridge = mock(CoreExtensionBridge.class);
-
- private CoreExtensionStopper underTest = new CoreExtensionStopper(componentContainer);
+ private final SpringComponentContainer componentContainer = new SpringComponentContainer();
+ private final CoreExtensionBridge bridge = mock(CoreExtensionBridge.class);
+ private final CoreExtensionStopper underTest = new CoreExtensionStopper(componentContainer);
@Test
public void stop_calls_stopPlugin_if_Bridge_exists_in_container() {
@Test
public void stop_does_not_call_stopPlugin_if_Bridge_does_not_exist_in_container() {
+ componentContainer.startComponents();
underTest.stop();
verifyNoMoreInteractions(bridge);
package org.sonar.server.issue.notification;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class IssuesChangesNotificationModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new IssuesChangesNotificationModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 7);
+ assertThat(container.getAddedObjects()).hasSize(7);
}
import org.sonar.api.platform.ServerStartHandler;
import org.sonar.api.platform.ServerStopHandler;
+import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
*/
@Test
public void doNotNotifyWithTheStartMethod() {
- ServerLifecycleNotifier notifier = new ServerLifecycleNotifier(server, new ServerStartHandler[]{start1, start2}, new ServerStopHandler[]{stop2});
+ ServerLifecycleNotifier notifier = new ServerLifecycleNotifier(server, new ServerStartHandler[] {start1, start2}, new ServerStopHandler[] {stop2});
notifier.start();
verify(start1, never()).onServerStart(server);
@Test
public void notifyOnStart() {
- ServerLifecycleNotifier notifier = new ServerLifecycleNotifier(server, new ServerStartHandler[]{start1, start2}, new ServerStopHandler[]{stop2});
+ ServerLifecycleNotifier notifier = new ServerLifecycleNotifier(server, new ServerStartHandler[] {start1, start2}, new ServerStopHandler[] {stop2});
notifier.notifyStart();
verify(start1).onServerStart(server);
verify(stop1, never()).onServerStop(server);
}
-
@Test
public void notifyOnStop() {
- ServerLifecycleNotifier notifier = new ServerLifecycleNotifier(server, new ServerStartHandler[]{start1, start2}, new ServerStopHandler[]{stop1, stop2});
+ ServerLifecycleNotifier notifier = new ServerLifecycleNotifier(server, new ServerStartHandler[] {start1, start2}, new ServerStopHandler[] {stop1, stop2});
notifier.stop();
verify(start1, never()).onServerStart(server);
verify(stop1).onServerStop(server);
verify(stop2).onServerStop(server);
}
+
+ @Test
+ public void null_handler_param_wont_lead_to_NPE() {
+ ServerLifecycleNotifier notifier = new ServerLifecycleNotifier(server, null, null);
+ assertThatNoException().isThrownBy(notifier::notifyStart);
+ assertThatNoException().isThrownBy(notifier::stop);
+ }
}
class FakeServer extends Server {
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import static org.sonar.api.utils.DateUtils.formatDateTime;
public class StartupMetadataProviderTest {
-
private static final long A_DATE = 1_500_000_000_000L;
-
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
- private StartupMetadataProvider underTest = new StartupMetadataProvider();
- private System2 system = mock(System2.class);
- private WebServer webServer = mock(WebServer.class);
+ private final StartupMetadataProvider underTest = new StartupMetadataProvider();
+ private final System2 system = mock(System2.class);
+ private final WebServer webServer = mock(WebServer.class);
@Test
public void generate_SERVER_STARTIME_but_do_not_persist_it_if_server_is_startup_leader() {
assertThat(metadata.getStartedAt()).isEqualTo(A_DATE);
assertNotPersistedProperty(CoreProperties.SERVER_STARTTIME);
-
- // keep a cache
- StartupMetadata secondMetadata = underTest.provide(system, runtime, webServer, dbTester.getDbClient());
- assertThat(secondMetadata).isSameAs(metadata);
}
@Test
// still in database
assertPersistedProperty(CoreProperties.SERVER_STARTTIME, formatDateTime(A_DATE));
- // keep a cache
- StartupMetadata secondMetadata = underTest.provide(system, runtime, webServer, dbTester.getDbClient());
- assertThat(secondMetadata).isSameAs(metadata);
-
- verifyZeroInteractions(system);
+ verifyNoInteractions(system);
}
private void assertPersistedProperty(String propertyKey, String expectedValue) {
import static org.mockito.Mockito.when;
public class TempFolderProviderTest {
-
-
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- TempFolderProvider underTest = new TempFolderProvider();
+ private final TempFolderProvider underTest = new TempFolderProvider();
@Test
public void existing_temp_dir() throws Exception {
import org.sonar.api.SonarEdition;
import org.sonar.api.SonarQubeSide;
import org.sonar.api.SonarRuntime;
+import org.sonar.api.config.Configuration;
import org.sonar.api.internal.SonarRuntimeImpl;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.Version;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginRepository;
public class ServerExtensionInstallerTest {
private SonarRuntime sonarRuntime = SonarRuntimeImpl.forSonarQube(Version.parse("8.0"), SonarQubeSide.SERVER, SonarEdition.COMMUNITY);
private TestPluginRepository pluginRepository = new TestPluginRepository();
-
private TestServerExtensionInstaller underTest = new TestServerExtensionInstaller(sonarRuntime, pluginRepository);
@Test
PluginInfo fooPluginInfo = newPlugin("foo", "Foo");
Plugin fooPlugin = mock(Plugin.class);
pluginRepository.add(fooPluginInfo, fooPlugin);
- ComponentContainer componentContainer = new ComponentContainer();
+ ListContainer componentContainer = new ListContainer();
underTest.installExtensions(componentContainer);
- assertThat(componentContainer.getPicoContainer().getComponents()).contains(fooPlugin);
+ assertThat(componentContainer.getAddedObjects()).contains(fooPlugin);
}
private static PluginInfo newPlugin(String key, String name) {
private static class TestServerExtensionInstaller extends ServerExtensionInstaller {
protected TestServerExtensionInstaller(SonarRuntime sonarRuntime, PluginRepository pluginRepository) {
- super(sonarRuntime, pluginRepository, singleton(ServerSide.class));
+ super(mock(Configuration.class), sonarRuntime, pluginRepository, singleton(ServerSide.class));
}
}
public class OkHttpClientProviderTest {
- private MapSettings settings = new MapSettings();
- private SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.parse("6.2"), SonarQubeSide.SERVER, SonarEdition.COMMUNITY);
+ private final MapSettings settings = new MapSettings();
+ private final SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.parse("6.2"), SonarQubeSide.SERVER, SonarEdition.COMMUNITY);
private final OkHttpClientProvider underTest = new OkHttpClientProvider();
@Rule
assertThat(request.header("Proxy-Authorization")).isEqualTo("Basic " + Base64.getEncoder().encodeToString("the-login:the-password".getBytes()));
}
- @Test
- public void get_returns_a_singleton() {
- OkHttpClient client1 = underTest.provide(settings.asConfig(), runtime);
- OkHttpClient client2 = underTest.provide(settings.asConfig(), runtime);
- assertThat(client2).isNotNull().isSameAs(client1);
- }
-
private RecordedRequest call(OkHttpClient client) throws IOException, InterruptedException {
server.enqueue(new MockResponse().setBody("pong"));
client.newCall(new Request.Builder().url(server.url("/ping")).build()).execute();
package org.sonar.server.webhook;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- assertThat(container.size()).isNotZero();
+ assertThat(container.getAddedObjects().size()).isNotZero();
}
}
*/
package org.sonar.server.branch;
+import javax.annotation.Nullable;
+
public class BranchFeatureProxyImpl implements BranchFeatureProxy {
private final BranchFeatureExtension branchFeatureExtension;
- public BranchFeatureProxyImpl() {
- this.branchFeatureExtension = null;
- }
-
- public BranchFeatureProxyImpl(BranchFeatureExtension branchFeatureExtension) {
+ public BranchFeatureProxyImpl(@Nullable BranchFeatureExtension branchFeatureExtension) {
this.branchFeatureExtension = branchFeatureExtension;
}
*/
package org.sonar.server.platform;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ExtensionContainer;
public interface Platform {
void doStart();
Status status();
- ComponentContainer getContainer();
+ ExtensionContainer getContainer();
enum Status {
BOOTING, SAFEMODE, STARTING, UP
import java.util.Optional;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.extension.PluginRiskConsent;
import java.util.Objects;
import java.util.Optional;
import org.apache.commons.io.FileUtils;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.utils.HttpDownloader;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import static org.sonar.server.plugins.PluginType.BUNDLED;
import static org.sonar.server.plugins.PluginType.EXTERNAL;
+import javax.inject.Inject;
+
public class PluginJarLoader {
private static final Logger LOG = Loggers.get(PluginJarLoader.class);
private final SonarRuntime runtime;
private final Set<String> blacklistedPluginKeys;
+ @Inject
public PluginJarLoader(ServerFileSystem fs, SonarRuntime runtime) {
this(fs, runtime, DEFAULT_BLACKLISTED_PLUGINS);
}
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.io.FileUtils;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.platform.PluginInfo;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.Plugin;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
package org.sonar.server.plugins;
import org.sonar.api.SonarRuntime;
+import org.sonar.api.config.Configuration;
import org.sonar.api.server.ServerSide;
import org.sonar.core.platform.PluginRepository;
@ServerSide
public class WebServerExtensionInstaller extends ServerExtensionInstaller {
- public WebServerExtensionInstaller(SonarRuntime sonarRuntime, PluginRepository pluginRepository) {
- super(sonarRuntime, pluginRepository, singleton(ServerSide.class));
+ public WebServerExtensionInstaller(Configuration configuration, SonarRuntime sonarRuntime, PluginRepository pluginRepository) {
+ super(configuration, sonarRuntime, pluginRepository, singleton(ServerSide.class));
}
}
import java.util.function.Consumer;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.springframework.beans.factory.annotation.Autowired;
import static com.google.common.base.Preconditions.checkNotNull;
private final ProjectLifeCycleListener[] listeners;
/**
- * Used by Pico when there is no ProjectLifeCycleListener implementation in container.
+ * Used by the container when there is no ProjectLifeCycleListener implementation in container.
*/
+ @Autowired(required = false)
public ProjectLifeCycleListenersImpl() {
this.listeners = new ProjectLifeCycleListener[0];
}
/**
- * Used by Pico when there is at least one ProjectLifeCycleListener implementation in container.
+ * Used by the container when there is at least one ProjectLifeCycleListener implementation in container.
*/
+ @Autowired(required = false)
public ProjectLifeCycleListenersImpl(ProjectLifeCycleListener[] listeners) {
this.listeners = listeners;
}
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import javax.annotation.Nullable;
import org.sonar.api.issue.Issue;
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.log.Logger;
/**
* Broadcast a given collection of {@link QGChangeEvent} for a specific trigger to all the registered
- * {@link QGChangeEventListener} in Pico.
+ * {@link QGChangeEventListener} in the ioc container.
*
* This class ensures that an {@link Exception} occurring calling one of the {@link QGChangeEventListener} doesn't
* prevent from calling the others.
private final QGChangeEventListener[] listeners;
- /**
- * Used by Pico when there is no QGChangeEventListener instance in container.
- */
- public QGChangeEventListenersImpl() {
- this.listeners = new QGChangeEventListener[0];
- }
-
- public QGChangeEventListenersImpl(QGChangeEventListener[] listeners) {
- this.listeners = listeners;
+ public QGChangeEventListenersImpl(@Nullable QGChangeEventListener[] listeners) {
+ this.listeners = listeners != null ? listeners : new QGChangeEventListener[0];
}
@Override
import org.sonar.api.config.GlobalPropertyChangeHandler;
import javax.annotation.Nullable;
+import org.springframework.beans.factory.annotation.Autowired;
public class SettingsChangeNotifier {
@VisibleForTesting
GlobalPropertyChangeHandler[] changeHandlers;
+ @Autowired(required = false)
public SettingsChangeNotifier(GlobalPropertyChangeHandler[] changeHandlers) {
this.changeHandlers = changeHandlers;
}
+ @Autowired(required = false)
public SettingsChangeNotifier() {
this(new GlobalPropertyChangeHandler[0]);
}
@Test
public void return_false_when_no_extension() {
- assertThat(new BranchFeatureProxyImpl().isEnabled()).isFalse();
+ assertThat(new BranchFeatureProxyImpl(null).isEnabled()).isFalse();
}
@Test
@Test
public void broadcastOnIssueChange_has_no_effect_when_no_listener() {
- QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl();
+ QGChangeEventListenersImpl underTest = new QGChangeEventListenersImpl(null);
underTest.broadcastOnIssueChange(oneIssueOnComponent1, singletonList(component1QGChangeEvent));
package org.sonar.server.util;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class TypeValidationModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new TypeValidationModule().configure(container);
- assertThat(container.size()).isEqualTo(11);
+ assertThat(container.getAddedObjects()).hasSize(9);
}
}
*/
package org.sonar.server.authentication;
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Ordering;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
-import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.sonar.api.server.authentication.IdentityProvider;
public class IdentityProviderRepository {
+ private static final Predicate<IdentityProvider> IS_ENABLED_FILTER = IdentityProvider::isEnabled;
+ private static final Function<IdentityProvider, String> TO_NAME = IdentityProvider::getName;
protected final Map<String, IdentityProvider> providersByKey = new HashMap<>();
- public IdentityProviderRepository(List<IdentityProvider> identityProviders) {
- this.providersByKey.putAll(FluentIterable.from(identityProviders).uniqueIndex(ToKey.INSTANCE));
- }
-
- /**
- * Used by pico when no identity provider available
- */
- public IdentityProviderRepository() {
- // nothing to do
+ public IdentityProviderRepository(@Nullable List<IdentityProvider> identityProviders) {
+ Optional.ofNullable(identityProviders)
+ .ifPresent(list -> list.forEach(i -> providersByKey.put(i.getKey(), i)));
}
public IdentityProvider getEnabledByKey(String key) {
IdentityProvider identityProvider = providersByKey.get(key);
- if (identityProvider != null && IsEnabledFilter.INSTANCE.apply(identityProvider)) {
+ if (identityProvider != null && IS_ENABLED_FILTER.test(identityProvider)) {
return identityProvider;
}
throw new IllegalArgumentException(String.format("Identity provider %s does not exist or is not enabled", key));
public List<IdentityProvider> getAllEnabledAndSorted() {
return providersByKey.values().stream()
- .filter(IsEnabledFilter.INSTANCE)
- .sorted(Ordering.natural().onResultOf(ToName.INSTANCE))
+ .filter(IS_ENABLED_FILTER)
+ .sorted(Comparator.comparing(TO_NAME))
.collect(Collectors.toList());
}
- private enum IsEnabledFilter implements Predicate<IdentityProvider> {
- INSTANCE;
-
- @Override
- public boolean apply(@Nonnull IdentityProvider input) {
- return input.isEnabled();
- }
- }
-
- private enum ToKey implements Function<IdentityProvider, String> {
- INSTANCE;
-
- @Override
- public String apply(@Nonnull IdentityProvider input) {
- return input.getKey();
- }
- }
-
- private enum ToName implements Function<IdentityProvider, String> {
- INSTANCE;
-
- @Override
- public String apply(@Nonnull IdentityProvider input) {
- return input.getName();
- }
- }
}
import org.sonar.api.platform.Server;
import org.sonar.api.server.authentication.OAuth2IdentityProvider;
import org.sonar.api.utils.log.Loggers;
+import org.springframework.beans.factory.annotation.Autowired;
public class LogOAuthWarning implements Startable {
private final Server server;
private final OAuth2IdentityProvider[] providers;
+ @Autowired(required = false)
public LogOAuthWarning(Server server, OAuth2IdentityProvider[] providers) {
this.server = server;
this.providers = providers;
}
/**
- * Used by default by picocontainer when no OAuth2IdentityProvider are present
+ * Used by default by the ioc container when no OAuth2IdentityProvider are present
*/
+ @Autowired(required = false)
public LogOAuthWarning(Server server) {
this(server, new OAuth2IdentityProvider[0]);
}
import org.sonar.db.user.UserDto;
import org.sonar.server.user.UserSession;
import org.sonar.server.user.UserSessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
public class RequestAuthenticatorImpl implements RequestAuthenticator {
private final UserSessionFactory userSessionFactory;
private final List<CustomAuthentication> customAuthentications;
+ @Autowired(required = false)
public RequestAuthenticatorImpl(JwtHttpHandler jwtHttpHandler, BasicAuthentication basicAuthentication, HttpHeadersAuthentication httpHeadersAuthentication,
UserSessionFactory userSessionFactory, CustomAuthentication[] customAuthentications) {
this.jwtHttpHandler = jwtHttpHandler;
this.customAuthentications = Arrays.asList(customAuthentications);
}
+ @Autowired(required = false)
public RequestAuthenticatorImpl(JwtHttpHandler jwtHttpHandler, BasicAuthentication basicAuthentication, HttpHeadersAuthentication httpHeadersAuthentication,
UserSessionFactory userSessionFactory) {
this(jwtHttpHandler, basicAuthentication, httpHeadersAuthentication, userSessionFactory, new CustomAuthentication[0]);
import org.sonar.api.server.ServerSide;
import org.sonar.api.platform.NewUserHandler;
import org.sonar.api.utils.log.Loggers;
+import org.springframework.beans.factory.annotation.Autowired;
/**
* @since 3.2
@ServerSide
public class NewUserNotifier {
- private NewUserHandler[] handlers;
+ private final NewUserHandler[] handlers;
+ @Autowired(required = false)
public NewUserNotifier(NewUserHandler[] handlers) {
this.handlers = handlers;
}
+ @Autowired(required = false)
public NewUserNotifier() {
this(new NewUserHandler[0]);
}
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Configuration;
import org.sonar.api.security.LoginPasswordAuthenticator;
import static org.sonar.process.ProcessProperties.Property.SONAR_AUTHENTICATOR_IGNORE_STARTUP_FAILURE;
import static org.sonar.process.ProcessProperties.Property.SONAR_SECURITY_REALM;
+import org.springframework.beans.factory.annotation.Autowired;
/**
* @since 2.14
private final boolean ignoreStartupFailure;
private final SecurityRealm realm;
+ @Autowired(required = false)
public SecurityRealmFactory(Configuration config, SecurityRealm[] realms, LoginPasswordAuthenticator[] authenticators) {
ignoreStartupFailure = config.getBoolean(SONAR_AUTHENTICATOR_IGNORE_STARTUP_FAILURE.getKey()).orElse(false);
String realmName = config.get(SONAR_SECURITY_REALM.getKey()).orElse(null);
realm = selectedRealm;
}
+ @Autowired(required = false)
public SecurityRealmFactory(Configuration config, LoginPasswordAuthenticator[] authenticators) {
this(config, new SecurityRealm[0], authenticators);
}
+ @Autowired(required = false)
public SecurityRealmFactory(Configuration config, SecurityRealm[] realms) {
this(config, realms, new LoginPasswordAuthenticator[0]);
}
+ @Autowired(required = false)
public SecurityRealmFactory(Configuration config) {
this(config, new SecurityRealm[0], new LoginPasswordAuthenticator[0]);
}
import java.util.function.Consumer;
import java.util.stream.Stream;
import javax.annotation.Nullable;
+import javax.inject.Inject;
import org.apache.commons.lang.math.RandomUtils;
import org.sonar.api.config.Configuration;
import org.sonar.api.platform.NewUserHandler;
private final DefaultGroupFinder defaultGroupFinder;
private final Configuration config;
private final AuditPersister auditPersister;
-
private final CredentialsLocalAuthentication localAuthentication;
- public UserUpdater(NewUserNotifier newUserNotifier, DbClient dbClient, UserIndexer userIndexer, DefaultGroupFinder defaultGroupFinder, Configuration config,
- CredentialsLocalAuthentication localAuthentication) {
- this.newUserNotifier = newUserNotifier;
- this.dbClient = dbClient;
- this.userIndexer = userIndexer;
- this.defaultGroupFinder = defaultGroupFinder;
- this.config = config;
- this.auditPersister = null;
- this.localAuthentication = localAuthentication;
- }
-
+ @Inject
public UserUpdater(NewUserNotifier newUserNotifier, DbClient dbClient, UserIndexer userIndexer, DefaultGroupFinder defaultGroupFinder, Configuration config,
AuditPersister auditPersister, CredentialsLocalAuthentication localAuthentication) {
this.newUserNotifier = newUserNotifier;
if (updateUser.isPasswordChanged() && validatePasswords(password, messages) && checkPasswordChangeAllowed(userDto, messages)) {
localAuthentication.storeHashPassword(userDto, password);
userDto.setResetPassword(false);
- if (auditPersister != null) {
- auditPersister.updateUserPassword(dbSession, new SecretNewValue("userLogin", userDto.getLogin()));
- }
+ auditPersister.updateUserPassword(dbSession, new SecretNewValue("userLogin", userDto.getLogin()));
return true;
}
return false;
package org.sonar.server.authentication;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class AuthenticationModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new AuthenticationModule().configure(container);
- assertThat(container.size()).isGreaterThan(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER);
+ assertThat(container.getAddedObjects()).isNotEmpty();
}
-
}
.hasMessage("Identity provider disabled does not exist or is not enabled");
}
+ @Test
+ public void fail_on_non_exist_provider() {
+ IdentityProviderRepository underTest = new IdentityProviderRepository(asList(GITHUB, BITBUCKET, DISABLED));
+
+ assertThatThrownBy(() -> underTest.getEnabledByKey("NotExist"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Identity provider NotExist does not exist or is not enabled");
+ }
+
@Test
public void return_all_enabled_providers() {
IdentityProviderRepository underTest = new IdentityProviderRepository(asList(GITHUB, BITBUCKET, DISABLED));
@Test
public void return_nothing_when_no_identity_provider() {
- IdentityProviderRepository underTest = new IdentityProviderRepository();
+ IdentityProviderRepository underTest = new IdentityProviderRepository(null);
assertThat(underTest.getAllEnabledAndSorted()).isEmpty();
}
package org.sonar.server.usertoken;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class UserTokenModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new UserTokenModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
+ assertThat(container.getAddedObjects()).hasSize(2);
}
}
public class IdentityProviderRepositoryRule extends IdentityProviderRepository implements TestRule {
+ public IdentityProviderRepositoryRule() {
+ super(null);
+ }
+
public IdentityProviderRepositoryRule addIdentityProvider(IdentityProvider identityProvider) {
providersByKey.put(identityProvider.getKey(), identityProvider);
return this;
compile 'org.apache.logging.log4j:log4j-api'
compile 'org.apache.tomcat.embed:tomcat-embed-core'
compile 'org.apache.commons:commons-dbcp2'
- compile 'org.picocontainer:picocontainer'
compile 'org.slf4j:jul-to-slf4j'
compile 'org.slf4j:slf4j-api'
compile 'org.sonarsource.update-center:sonar-update-center-common'
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.Properties;
import org.sonar.api.Property;
import org.sonar.api.config.Configuration;
*/
package org.sonar.server.platform;
-import javax.annotation.Nullable;
import org.sonar.api.Startable;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.MessageException;
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+
@ServerSide
public class ClusterVerification implements Startable {
@Nullable
private final ClusterFeature feature;
+ @Inject
public ClusterVerification(WebServer server, @Nullable ClusterFeature feature) {
this.server = server;
this.feature = feature;
package org.sonar.server.platform;
import java.util.Optional;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.log.Logger;
import java.util.Optional;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.platform.ServerUpgradeStatus;
import org.sonar.process.ProcessProperties;
*/
package org.sonar.server.platform.db;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.platform.ServerUpgradeStatus;
import org.sonar.server.platform.db.migration.charset.DatabaseCharsetChecker;
import java.sql.SQLException;
import org.h2.Driver;
import org.h2.tools.Server;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger;
package org.sonar.server.platform.db;
import com.google.common.annotations.VisibleForTesting;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.System2;
*/
package org.sonar.server.platform.db.migration;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.utils.log.Loggers;
import org.sonar.server.platform.DefaultServerUpgradeStatus;
import org.sonar.server.platform.db.migration.engine.MigrationEngine;
*/
package org.sonar.server.platform.monitoring;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.process.Jmx;
import org.sonar.process.systeminfo.SystemInfoSection;
package org.sonar.server.platform.serverid;
import java.util.Optional;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.SonarQubeSide;
import org.sonar.api.SonarRuntime;
import org.sonar.api.utils.log.Logger;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.resources.Languages;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleScope;
import org.sonar.api.server.rule.RulesDefinition;
import org.sonar.api.impl.server.RulesDefinitionContext;
import org.sonar.server.plugins.ServerPluginRepository;
+import org.springframework.beans.factory.annotation.Autowired;
/**
* Loads all instances of {@link RulesDefinition}. Used during server startup
private final RulesDefinition[] pluginDefs;
private final ServerPluginRepository serverPluginRepository;
+ @Autowired(required = false)
public RuleDefinitionsLoader(CommonRuleDefinitions coreCommonDefs, ServerPluginRepository serverPluginRepository, RulesDefinition[] pluginDefs) {
this.coreCommonDefs = coreCommonDefs;
this.serverPluginRepository = serverPluginRepository;
/**
* Used when no definitions at all.
*/
+ @Autowired(required = false)
public RuleDefinitionsLoader(CommonRuleDefinitions coreCommonDefs, ServerPluginRepository serverPluginRepository) {
this(coreCommonDefs, serverPluginRepository, new RulesDefinition[0]);
}
*/
package org.sonar.server.startup;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.log.Loggers;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.Metrics;
import static com.google.common.collect.FluentIterable.concat;
import static com.google.common.collect.Lists.newArrayList;
+import org.springframework.beans.factory.annotation.Autowired;
public class RegisterMetrics implements Startable {
private final UuidFactory uuidFactory;
private final Metrics[] metricsRepositories;
+ @Autowired(required = false)
public RegisterMetrics(DbClient dbClient, UuidFactory uuidFactory, Metrics[] metricsRepositories) {
this.dbClient = dbClient;
this.uuidFactory = uuidFactory;
/**
* Used when no plugin is defining Metrics
*/
+ @Autowired(required = false)
public RegisterMetrics(DbClient dbClient, UuidFactory uuidFactory) {
this(dbClient, uuidFactory, new Metrics[] {});
}
import java.util.Date;
import java.util.Optional;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.security.DefaultGroups;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger;
package org.sonar.server.startup;
import com.google.common.base.Strings;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.PropertyDefinition;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.utils.log.Loggers;
*/
package org.sonar.server.startup;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.SonarEdition;
import org.sonar.api.SonarRuntime;
import org.sonar.api.server.ServerSide;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.System2;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+import javax.inject.Inject;
import org.sonar.api.config.Configuration;
import org.sonar.api.platform.Server;
import org.sonar.api.server.ServerSide;
@CheckForNull
private final LicenseReader licenseReader;
- public TelemetryDataLoaderImpl(Server server, DbClient dbClient, PluginRepository pluginRepository, UserIndex userIndex, ProjectMeasuresIndex projectMeasuresIndex,
- PlatformEditionProvider editionProvider, InternalProperties internalProperties, Configuration configuration, DockerSupport dockerSupport) {
- this(server, dbClient, pluginRepository, userIndex, projectMeasuresIndex, editionProvider, internalProperties, configuration, dockerSupport, null);
- }
-
+ @Inject
public TelemetryDataLoaderImpl(Server server, DbClient dbClient, PluginRepository pluginRepository, UserIndex userIndex, ProjectMeasuresIndex projectMeasuresIndex,
PlatformEditionProvider editionProvider, InternalProperties internalProperties, Configuration configuration,
DockerSupport dockerSupport, @Nullable LicenseReader licenseReader) {
package org.sonar.server.ce;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class CeModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new CeModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 3);
+ assertThat(container.getAddedObjects()).hasSize(3);
}
-
-
}
package org.sonar.server.notification;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class NotificationModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new NotificationModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 5);
+ assertThat(container.getAddedObjects()).hasSize(5);
}
}
*/
package org.sonar.server.platform;
-import java.util.Collection;
import org.junit.Test;
-import org.picocontainer.ComponentAdapter;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class SystemInfoWriterModuleTest {
- private WebServer webServer = mock(WebServer.class);
- private SystemInfoWriterModule underTest = new SystemInfoWriterModule(webServer);
+ private final WebServer webServer = mock(WebServer.class);
+ private final SystemInfoWriterModule underTest = new SystemInfoWriterModule(webServer);
@Test
public void verify_system_info_configuration_in_cluster_mode() {
when(webServer.isStandalone()).thenReturn(false);
- ComponentContainer container = new ComponentContainer();
-
+ ListContainer container = new ListContainer();
underTest.configure(container);
-
- Collection<ComponentAdapter<?>> adapters = container.getPicoContainer().getComponentAdapters();
- assertThat(adapters)
- .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 20);
+ assertThat(container.getAddedObjects()).hasSize(20);
}
@Test
public void verify_system_info_configuration_in_standalone_mode() {
when(webServer.isStandalone()).thenReturn(true);
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
-
- Collection<ComponentAdapter<?>> adapters = container.getPicoContainer().getComponentAdapters();
- assertThat(adapters)
- .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 14);
+ assertThat(container.getAddedObjects()).hasSize(14);
}
-
}
import org.sonar.api.server.ServerSide;
import org.sonar.core.extension.CoreExtension;
import org.sonar.core.extension.CoreExtensionRepository;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter;
public class WebCoreExtensionsInstallerTest {
- private SonarRuntime sonarRuntime = mock(SonarRuntime.class);
- private CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class);
-
- private WebCoreExtensionsInstaller underTest = new WebCoreExtensionsInstaller(sonarRuntime, coreExtensionRepository);
+ private final SonarRuntime sonarRuntime = mock(SonarRuntime.class);
+ private final CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class);
+ private final WebCoreExtensionsInstaller underTest = new WebCoreExtensionsInstaller(sonarRuntime, coreExtensionRepository);
@Test
public void install_only_adds_ServerSide_annotated_extension_to_container() {
NoAnnotationClass.class, OtherAnnotationClass.class, MultipleAnnotationClass.class);
}
}));
- ComponentContainer container = new ComponentContainer();
-
+ ListContainer container = new ListContainer();
underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
- assertThat(container.getPicoContainer().getComponentAdapters())
- .hasSize(ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
- assertThat(container.getComponentByType(WebServerClass.class)).isNotNull();
- assertThat(container.getComponentByType(MultipleAnnotationClass.class)).isNotNull();
+ assertThat(container.getAddedObjects()).containsOnly(WebServerClass.class, MultipleAnnotationClass.class);
}
@ComputeEngineSide
package org.sonar.server.platform.serverid;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class ServerIdModuleTest {
- private ServerIdModule underTest = new ServerIdModule();
+ private final ServerIdModule underTest = new ServerIdModule();
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 4);
+ assertThat(container.getAddedObjects()).hasSize(4);
}
-
}
package org.sonar.server.platform.web.requestid;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class HttpRequestIdModuleTest {
- private HttpRequestIdModule underTest = new HttpRequestIdModule();
+ private final HttpRequestIdModule underTest = new HttpRequestIdModule();
@Test
public void count_components_in_module() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
-
- assertThat(container.getPicoContainer().getComponentAdapters())
- .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 3);
+ assertThat(container.getAddedObjects()).hasSize(3);
}
}
package org.sonar.server.qualitygate;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class ProjectsInWarningModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new ProjectsInWarningModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
+ assertThat(container.getAddedObjects()).hasSize(2);
}
-
}
import org.sonar.server.platform.DockerSupport;
import org.sonar.server.property.InternalProperties;
import org.sonar.server.property.MapInternalProperties;
-import org.sonar.server.pushapi.sonarlint.SonarLintClientsRegistry;
import org.sonar.server.user.index.UserIndex;
import org.sonar.server.user.index.UserIndexer;
import org.sonar.updatecenter.common.Version;
private final LicenseReader licenseReader = mock(LicenseReader.class);
private final TelemetryDataLoader communityUnderTest = new TelemetryDataLoaderImpl(server, db.getDbClient(), pluginRepository, new UserIndex(es.client(), system2),
- new ProjectMeasuresIndex(es.client(), null, system2), editionProvider, internalProperties, configuration, dockerSupport);
+ new ProjectMeasuresIndex(es.client(), null, system2), editionProvider, internalProperties, configuration, dockerSupport, null);
private final TelemetryDataLoader commercialUnderTest = new TelemetryDataLoaderImpl(server, db.getDbClient(), pluginRepository, new UserIndex(es.client(), system2),
new ProjectMeasuresIndex(es.client(), null, system2), editionProvider, internalProperties, configuration, dockerSupport, licenseReader);
package org.sonar.server.updatecenter;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class UpdateCenterModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new UpdateCenterModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
+ assertThat(container.getAddedObjects()).hasSize(2);
}
}
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.common.settings.Settings;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.log.Logger;
import java.util.HashMap;
import java.util.Map;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.server.ServerSide;
import org.sonar.server.es.newindex.BuiltIndex;
import static java.util.Collections.emptyList;
import static org.sonar.core.util.stream.MoreCollectors.toArrayList;
+import org.springframework.beans.factory.annotation.Autowired;
/**
* Populates the types "authorization" of each index requiring project
private final Collection<AuthorizationScope> authorizationScopes;
private final Map<String, IndexType> indexTypeByFormat;
+ @Autowired(required = false)
public PermissionIndexer(DbClient dbClient, EsClient esClient, NeedAuthorizationIndexer... needAuthorizationIndexers) {
this(dbClient, esClient, Arrays.stream(needAuthorizationIndexers)
.map(NeedAuthorizationIndexer::getAuthorizationScope)
}
@VisibleForTesting
+ @Autowired(required = false)
public PermissionIndexer(DbClient dbClient, EsClient esClient, Collection<AuthorizationScope> authorizationScopes) {
this.dbClient = dbClient;
this.esClient = esClient;
package org.sonar.server.measure.index;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class ProjectsEsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new ProjectsEsModule().configure(container);
- assertThat(container.size()).isEqualTo(3 + COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER);
+ assertThat(container.getAddedObjects()).hasSize(3);
}
}
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
package org.sonar.server.pushapi;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class ServerPushWsModuleTest {
-
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
-
+ ListContainer container = new ListContainer();
new ServerPushWsModule().configure(container);
-
- assertThat(container.size()).isPositive();
+ assertThat(container.getAddedObjects()).isNotEmpty();
}
}
import org.apache.commons.io.filefilter.HiddenFileFilter;
import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.server.ServerSide;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.platform.ServerFileSystem;
@CheckForNull
private final BranchSupportDelegate delegate;
- /**
- * Constructor called by Pico when no implementation of {@link BranchSupportDelegate} is available.
- */
- public BranchSupport() {
- this(null);
- }
-
public BranchSupport(@Nullable BranchSupportDelegate delegate) {
this.delegate = delegate;
}
package org.sonar.server.ce.queue;
import java.util.List;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.platform.ServerUpgradeStatus;
import org.sonar.api.server.ServerSide;
package org.sonar.server.ce.ws;
import javax.annotation.Nullable;
+import javax.inject.Inject;
+
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
private final UserSession userSession;
private final WorkerCountProvider workerCountProvider;
+ @Inject
public WorkerCountAction(UserSession userSession, @Nullable WorkerCountProvider workerCountProvider) {
this.userSession = userSession;
this.workerCountProvider = workerCountProvider;
package org.sonar.server.duplication.ws;
import com.google.common.annotations.VisibleForTesting;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
+import static java.util.Optional.ofNullable;
import org.apache.commons.lang.StringUtils;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonarqube.ws.Duplications.Block;
import org.sonarqube.ws.Duplications.ShowResponse;
-import static java.util.Optional.ofNullable;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
public class ShowResponseBuilder {
private final ComponentDao componentDao;
+ @Inject
public ShowResponseBuilder(DbClient dbClient) {
this.componentDao = dbClient.componentDao();
}
import org.sonar.process.cluster.health.NodeHealth;
import org.sonar.process.cluster.health.SharedHealthState;
import org.sonar.server.platform.WebServer;
+import org.springframework.beans.factory.annotation.Autowired;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.copyOf;
private final SharedHealthState sharedHealthState;
/**
- * Constructor used by Pico in standalone mode and in safe mode.
+ * Constructor used by the ioc container in standalone mode and in safe mode.
*/
+ @Autowired(required = false)
public HealthCheckerImpl(WebServer webServer, NodeHealthCheck[] nodeHealthChecks) {
this(webServer, nodeHealthChecks, new ClusterHealthCheck[0], null);
}
/**
- * Constructor used by Pico in cluster mode.
+ * Constructor used by the ioc container in cluster mode.
*/
+ @Autowired(required = false)
public HealthCheckerImpl(WebServer webServer, NodeHealthCheck[] nodeHealthChecks, ClusterHealthCheck[] clusterHealthChecks,
@Nullable SharedHealthState sharedHealthState) {
this.webServer = webServer;
import java.util.Arrays;
import java.util.stream.Collectors;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.resources.Language;
import org.sonar.server.plugins.ServerPluginRepository;
+import org.springframework.beans.factory.annotation.Autowired;
public class LanguageValidation implements Startable {
private final ServerPluginRepository pluginRepository;
private final Language[] languages;
+ @Autowired(required = false)
public LanguageValidation(ServerPluginRepository pluginRepository) {
this.pluginRepository = pluginRepository;
this.languages = new Language[0];
}
+ @Autowired(required = false)
public LanguageValidation(ServerPluginRepository pluginRepository, Language... languages) {
this.pluginRepository = pluginRepository;
this.languages = languages;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.server.notification.NotificationDispatcherMetadata;
+import org.springframework.beans.factory.annotation.Autowired;
public class NotificationCenter {
private final NotificationDispatcherMetadata[] dispatchersMetadata;
private final NotificationChannel[] channels;
+ @Autowired(required = false)
public NotificationCenter(NotificationDispatcherMetadata[] metadata, NotificationChannel[] channels) {
this.dispatchersMetadata = metadata;
this.channels = channels;
/**
* Default constructor when no channels.
*/
+ @Autowired(required = false)
public NotificationCenter(NotificationDispatcherMetadata[] metadata) {
this(metadata, new NotificationChannel[0]);
LOG.warn("There is no notification channel - no notification will be delivered!");
/**
* Default constructor when no dispatcher metadata.
*/
+ @Autowired(required = false)
public NotificationCenter(NotificationChannel[] channels) {
this(new NotificationDispatcherMetadata[0], channels);
}
+ @Autowired(required = false)
public NotificationCenter() {
this(new NotificationDispatcherMetadata[0], new NotificationChannel[0]);
LOG.warn("There is no notification channel - no notification will be delivered!");
*/
package org.sonar.server.platform.ws;
+import javax.annotation.Nullable;
import org.sonar.server.health.CeStatusNodeCheck;
import org.sonar.server.health.DbConnectionNodeCheck;
import org.sonar.server.health.EsStatusNodeCheck;
private final DbConnectionNodeCheck dbConnectionNodeCheck;
private final CeStatusNodeCheck ceStatusNodeCheck;
+ @Nullable
private final EsStatusNodeCheck esStatusNodeCheck;
private final WebServerStatusNodeCheck webServerStatusNodeCheck;
public LivenessCheckerImpl(DbConnectionNodeCheck dbConnectionNodeCheck,
- WebServerStatusNodeCheck webServerStatusNodeCheck, CeStatusNodeCheck ceStatusNodeCheck, EsStatusNodeCheck esStatusNodeCheck) {
+ WebServerStatusNodeCheck webServerStatusNodeCheck, CeStatusNodeCheck ceStatusNodeCheck, @Nullable EsStatusNodeCheck esStatusNodeCheck) {
this.dbConnectionNodeCheck = dbConnectionNodeCheck;
this.webServerStatusNodeCheck = webServerStatusNodeCheck;
this.ceStatusNodeCheck = ceStatusNodeCheck;
this.esStatusNodeCheck = esStatusNodeCheck;
}
- /**
- * Constructor used by Pico Container on non-standalone mode, so on a DCE App Node, where EsStatusNodeCheck is not available
- */
- public LivenessCheckerImpl(DbConnectionNodeCheck dbConnectionNodeCheck,
- WebServerStatusNodeCheck webServerStatusNodeCheck, CeStatusNodeCheck ceStatusNodeCheck) {
- this.dbConnectionNodeCheck = dbConnectionNodeCheck;
- this.webServerStatusNodeCheck = webServerStatusNodeCheck;
- this.ceStatusNodeCheck = ceStatusNodeCheck;
- this.esStatusNodeCheck = null;
- }
-
public boolean liveness() {
if (!Health.Status.GREEN.equals(dbConnectionNodeCheck.check().getStatus())) {
import java.util.Map;
import java.util.Objects;
import javax.annotation.CheckForNull;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.NotFoundException;
+import org.springframework.beans.factory.annotation.Autowired;
import static org.sonar.server.exceptions.BadRequestException.checkRequest;
private final ProfileExporter[] exporters;
private final ProfileImporter[] importers;
+ @Autowired(required = false)
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, QProfileRules qProfileRules, ProfileExporter[] exporters, ProfileImporter[] importers) {
this.dbClient = dbClient;
this.ruleFinder = ruleFinder;
}
/**
- * Used by Pico if no {@link ProfileImporter} is found
+ * Used by the ioc container if no {@link ProfileImporter} is found
*/
+ @Autowired(required = false)
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, QProfileRules qProfileRules, ProfileExporter[] exporters) {
this(dbClient, ruleFinder, qProfileRules, exporters, new ProfileImporter[0]);
}
/**
- * Used by Pico if no {@link ProfileExporter} is found
+ * Used by the ioc container if no {@link ProfileExporter} is found
*/
+ @Autowired(required = false)
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, QProfileRules qProfileRules, ProfileImporter[] importers) {
this(dbClient, ruleFinder, qProfileRules, new ProfileExporter[0], importers);
}
/**
- * Used by Pico if no {@link ProfileImporter} nor {@link ProfileExporter} is found
+ * Used by the ioc container if no {@link ProfileImporter} nor {@link ProfileExporter} is found
*/
+ @Autowired(required = false)
public QProfileExporters(DbClient dbClient, RuleFinder ruleFinder, QProfileRules qProfileRules) {
this(dbClient, ruleFinder, qProfileRules, new ProfileExporter[0], new ProfileImporter[0]);
}
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger;
*/
package org.sonar.server.qualityprofile.builtin;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
/**
* Startable added to {@link org.sonar.server.platform.platformlevel.PlatformLevelStartup} responsible for initializing
import org.sonar.db.rule.DeprecatedRuleKeyDto;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.server.rule.ServerRuleFinder;
+import org.springframework.beans.factory.annotation.Autowired;
import static com.google.common.base.Preconditions.checkState;
private List<BuiltInQProfile> qProfiles;
/**
- * Requires for pico container when no {@link BuiltInQualityProfilesDefinition} is defined at all
+ * Used by the ioc container when no {@link BuiltInQualityProfilesDefinition} is defined at all
*/
+ @Autowired(required = false)
public BuiltInQProfileRepositoryImpl(DbClient dbClient, ServerRuleFinder ruleFinder, Languages languages) {
this(dbClient, ruleFinder, languages, new BuiltInQualityProfilesDefinition[0]);
}
+ @Autowired(required = false)
public BuiltInQProfileRepositoryImpl(DbClient dbClient, ServerRuleFinder ruleFinder, Languages languages, BuiltInQualityProfilesDefinition... definitions) {
this.dbClient = dbClient;
this.ruleFinder = ruleFinder;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_CREATE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_NAME;
+import org.springframework.beans.factory.annotation.Autowired;
public class CreateAction implements QProfileWsAction {
private final UserSession userSession;
private final ActiveRuleIndexer activeRuleIndexer;
+ @Autowired(required = false)
public CreateAction(DbClient dbClient, QProfileFactory profileFactory, QProfileExporters exporters, Languages languages,
UserSession userSession, ActiveRuleIndexer activeRuleIndexer, ProfileImporter... importers) {
this.dbClient = dbClient;
this.importers = importers;
}
+ @Autowired(required = false)
public CreateAction(DbClient dbClient, QProfileFactory profileFactory, QProfileExporters exporters, Languages languages,
UserSession userSession, ActiveRuleIndexer activeRuleIndexer) {
this(dbClient, profileFactory, exporters, languages, userSession, activeRuleIndexer, new ProfileImporter[0]);
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService.NewController;
import org.sonar.api.utils.text.JsonWriter;
+import org.springframework.beans.factory.annotation.Autowired;
public class ExportersAction implements QProfileWsAction {
- private ProfileExporter[] exporters;
+ private final ProfileExporter[] exporters;
+ @Autowired(required = false)
public ExportersAction(ProfileExporter[] exporters) {
this.exporters = exporters;
}
/**
- * Used by Pico if no {@link ProfileExporter} is found
+ * Used by the container if no {@link ProfileExporter} is found
*/
+ @Autowired(required = false)
public ExportersAction() {
this(new ProfileExporter[0]);
}
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.text.JsonWriter;
+import org.springframework.beans.factory.annotation.Autowired;
public class ImportersAction implements QProfileWsAction {
private final ProfileImporter[] importers;
+ @Autowired(required = false)
public ImportersAction(ProfileImporter[] importers) {
this.importers = importers;
}
+ @Autowired(required = false)
public ImportersAction() {
this(new ProfileImporter[0]);
}
import static org.sonar.api.web.page.Page.Scope.COMPONENT;
import static org.sonar.api.web.page.Page.Scope.GLOBAL;
import static org.sonar.core.util.stream.MoreCollectors.toList;
+import org.springframework.beans.factory.annotation.Autowired;
@ServerSide
public class PageRepository implements Startable {
private List<Page> pages;
/**
- * Used by Pico when there is no {@link PageDefinition}.
+ * Used by the ioc container when there is no {@link PageDefinition}.
*/
+ @Autowired(required = false)
public PageRepository(PluginRepository pluginRepository, CoreExtensionRepository coreExtensionRepository) {
this.pluginRepository = pluginRepository;
this.coreExtensionRepository = coreExtensionRepository;
}
/**
- * Used by Pico when there is only {@link PageDefinition} provided both by Plugin(s).
+ * Used by the ioc container when there is only {@link PageDefinition} provided both by Plugin(s).
*/
- public PageRepository(PluginRepository pluginRepository, CoreExtensionRepository coreExtensionRepository,
- PageDefinition[] pageDefinitions) {
+ @Autowired(required = false)
+ public PageRepository(PluginRepository pluginRepository, CoreExtensionRepository coreExtensionRepository, PageDefinition[] pageDefinitions) {
this.pluginRepository = pluginRepository;
this.coreExtensionRepository = coreExtensionRepository;
this.definitions = copyOf(pageDefinitions);
}
/**
- * Used by Pico when there is only {@link PageDefinition} provided both by Core Extension(s).
+ * Used by the ioc container when there is only {@link PageDefinition} provided both by Core Extension(s).
*/
- public PageRepository(PluginRepository pluginRepository, CoreExtensionRepository coreExtensionRepository,
- CorePageDefinition[] corePageDefinitions) {
+ @Autowired(required = false)
+ public PageRepository(PluginRepository pluginRepository, CoreExtensionRepository coreExtensionRepository, CorePageDefinition[] corePageDefinitions) {
this.pluginRepository = pluginRepository;
this.coreExtensionRepository = coreExtensionRepository;
this.definitions = emptyList();
}
/**
- * Used by Pico when there is {@link PageDefinition} provided both by Core Extension(s) and Plugin(s).
+ * Used by the ioc container when there is {@link PageDefinition} provided both by Core Extension(s) and Plugin(s).
*/
+ @Autowired(required = false)
public PageRepository(PluginRepository pluginRepository, CoreExtensionRepository coreExtensionRepository,
PageDefinition[] pageDefinitions, CorePageDefinition[] corePageDefinitions) {
this.pluginRepository = pluginRepository;
@Nullable
private final WebAnalytics analytics;
- public WebAnalyticsLoaderImpl(WebAnalytics[] analytics) {
- if (analytics.length > 1) {
- List<String> classes = Arrays.stream(analytics).map(a -> a.getClass().getName()).collect(Collectors.toList());
- throw MessageException.of("Limited to only one web analytics plugin. Found multiple implementations: " + classes);
+ public WebAnalyticsLoaderImpl(@Nullable WebAnalytics[] analytics) {
+ if (analytics == null) {
+ this.analytics = null;
+ } else {
+ if (analytics.length > 1) {
+ List<String> classes = Arrays.stream(analytics).map(a -> a.getClass().getName()).collect(Collectors.toList());
+ throw MessageException.of("Limited to only one web analytics plugin. Found multiple implementations: " + classes);
+ }
+ this.analytics = analytics.length == 1 ? analytics[0] : null;
}
- this.analytics = analytics.length == 1 ? analytics[0] : null;
- }
-
- public WebAnalyticsLoaderImpl() {
- this.analytics = null;
}
@Override
*/
package org.sonar.server.user.ws;
-import org.sonar.api.config.Configuration;
import org.sonar.core.platform.Module;
-import org.sonar.process.ProcessProperties;
public class UsersWsModule extends Module {
- private final Configuration configuration;
-
- public UsersWsModule(Configuration configuration) {
- this.configuration = configuration;
- }
@Override
protected void configureModule() {
SetSettingAction.class,
UpdateIdentityProviderAction.class);
- if (configuration.getBoolean(ProcessProperties.Property.SONARCLOUD_ENABLED.getKey()).orElse(false)) {
- // onboarding tutorial is available only in SonarCloud
- add(SkipOnboardingTutorialAction.class);
- }
}
}
package org.sonar.server.almintegration.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class AlmIntegrationsWSModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new AlmIntegrationsWSModule().configure(container);
- assertThat(container.size()).isPositive();
+ assertThat(container.getAddedObjects()).isNotEmpty();
}
-
}
package org.sonar.server.almsettings.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class AlmSettingsWsModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new AlmSettingsWsModule().configure(container);
- assertThat(container.size()).isPositive();
+ assertThat(container.getAddedObjects()).isNotEmpty();
}
-
}
package org.sonar.server.authentication.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class AuthenticationWsModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new AuthenticationWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 4);
+ assertThat(container.getAddedObjects()).hasSize(4);
}
}
package org.sonar.server.badge.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class ProjectBadgesWsModuleTest {
-
- private final ComponentContainer container = new ComponentContainer();
private final ProjectBadgesWsModule underTest = new ProjectBadgesWsModule();
@Test
public void verify_count_of_added_components() {
+ ListContainer container = new ListContainer();
underTest.configure(container);
-
- assertThat(container.size()).isPositive();
+ assertThat(container.getAddedObjects()).isNotEmpty();
}
-
}
package org.sonar.server.batch;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class BatchWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new BatchWsModule().configure(container);
- assertThat(container.size()).isEqualTo(9);
+ assertThat(container.getAddedObjects()).hasSize(7);
}
}
package org.sonar.server.branch.pr.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class PullRequestWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new PullRequestWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 3);
+ assertThat(container.getAddedObjects()).hasSize(3);
}
}
package org.sonar.server.branch.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class BranchWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new BranchWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 5);
+ assertThat(container.getAddedObjects()).hasSize(5);
}
}
private static final Map<String, String> NO_CHARACTERISTICS = Collections.emptyMap();
private final BranchSupportDelegate branchSupportDelegate = mock(BranchSupportDelegate.class);
- private final BranchSupport underTestNoBranch = new BranchSupport();
+ private final BranchSupport underTestNoBranch = new BranchSupport(null);
private final BranchSupport underTestWithBranch = new BranchSupport(branchSupportDelegate);
@Test
private final PermissionTemplateService permissionTemplateService = mock(PermissionTemplateService.class);
private final ComponentUpdater componentUpdater = new ComponentUpdater(db.getDbClient(), mock(I18n.class), mock(System2.class), permissionTemplateService,
new FavoriteUpdater(db.getDbClient()), projectIndexers, new SequenceUuidFactory());
- private final BranchSupport ossEditionBranchSupport = new BranchSupport();
+ private final BranchSupport ossEditionBranchSupport = new BranchSupport(null);
private final ReportSubmitter underTest = new ReportSubmitter(queue, userSession, componentUpdater, permissionTemplateService, db.getDbClient(), ossEditionBranchSupport,
projectDefaultVisibility);
package org.sonar.server.ce.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class CeWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new CeWsModule().configure(container);
- assertThat(container.size()).isEqualTo(20 + COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER);
+ assertThat(container.getAddedObjects()).hasSize(20);
}
}
package org.sonar.server.component.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class ComponentsWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new ComponentsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 7);
+ assertThat(container.getAddedObjects()).hasSize(7);
}
}
package org.sonar.server.email.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class EmailsWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new EmailsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(2 + 2);
+ assertThat(container.getAddedObjects()).hasSize(2);
}
}
package org.sonar.server.favorite;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class FavoriteModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new FavoriteModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
+ assertThat(container.getAddedObjects()).hasSize(2);
}
}
package org.sonar.server.favorite.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class FavoriteWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new FavoriteWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 4);
+ assertThat(container.getAddedObjects()).hasSize(4);
}
-
-
}
*/
package org.sonar.server.health;
-import java.util.Collection;
import java.util.Date;
-import java.util.List;
import java.util.Random;
-import java.util.stream.Collectors;
import org.junit.Test;
-import org.picocontainer.ComponentAdapter;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.System2;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.process.NetworkUtils;
import org.sonar.process.cluster.health.SharedHealthStateImpl;
import org.sonar.process.cluster.hz.HazelcastMember;
+import org.sonar.core.platform.ListContainer;
import static java.lang.String.valueOf;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.mockito.Mockito.when;
public class NodeHealthModuleTest {
- private Random random = new Random();
- private MapSettings mapSettings = new MapSettings();
- private NodeHealthModule underTest = new NodeHealthModule();
+ private final Random random = new Random();
+ private final MapSettings mapSettings = new MapSettings();
+ private final NodeHealthModule underTest = new NodeHealthModule();
@Test
public void no_broken_dependencies() {
- ComponentContainer container = new ComponentContainer();
+ SpringComponentContainer container = new SpringComponentContainer();
Server server = mock(Server.class);
NetworkUtils networkUtils = mock(NetworkUtils.class);
// settings required by NodeHealthProvider
@Test
public void provides_implementation_of_SharedHealthState() {
- ComponentContainer container = new ComponentContainer();
-
+ ListContainer container = new ListContainer();
underTest.configure(container);
- assertThat(classesAddedToContainer(container))
+ assertThat(container.getAddedObjects())
.contains(SharedHealthStateImpl.class);
}
-
- private List<Class<?>> classesAddedToContainer(ComponentContainer container) {
- Collection<ComponentAdapter<?>> componentAdapters = container.getPicoContainer().getComponentAdapters();
- return componentAdapters.stream().map(ComponentAdapter::getComponentImplementation).collect(Collectors.toList());
- }
}
package org.sonar.server.hotspot.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class HotspotsWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new HotspotsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 10);
+ assertThat(container.getAddedObjects()).hasSize(10);
}
-
}
package org.sonar.server.issue.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class IssueWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new IssueWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 31);
+ assertThat(container.getAddedObjects()).hasSize(31);
}
}
package org.sonar.server.measure.live;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class LiveMeasureModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new LiveMeasureModule().configure(container);
- assertThat(container.size()).isEqualTo(3 + 2);
+ assertThat(container.getAddedObjects()).hasSize(3);
}
-
-
}
package org.sonar.server.measure.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class MeasuresWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new MeasuresWsModule().configure(container);
- assertThat(container.size()).isEqualTo(5 + 2);
+ assertThat(container.getAddedObjects()).hasSize(5);
}
}
package org.sonar.server.metric.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class MetricsWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new MetricsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(5);
+ assertThat(container.getAddedObjects()).hasSize(3);
}
}
package org.sonar.server.monitoring;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class MonitoringWsModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new MonitoringWsModule().configure(container);
- assertThat(container.size()).isPositive();
+ assertThat(container.getAddedObjects()).hasSize(3);
}
-
}
package org.sonar.server.newcodeperiod.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class NewCodePeriodsWsModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new NewCodePeriodsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(7);
+ assertThat(container.getAddedObjects()).hasSize(5);
}
-
}
package org.sonar.server.notification.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class NotificationWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new NotificationWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 7);
+ assertThat(container.getAddedObjects()).hasSize(7);
}
}
package org.sonar.server.permission.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class PermissionsWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new PermissionsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 26);
+ assertThat(container.getAddedObjects()).hasSize(26);
}
}
*/
package org.sonar.server.platform.ws;
-import java.util.Collection;
import org.junit.Test;
-import org.picocontainer.ComponentAdapter;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import org.sonar.server.platform.WebServer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class ChangeLogLevelServiceModuleTest {
- private WebServer webServer = mock(WebServer.class);
- private ChangeLogLevelServiceModule underTest = new ChangeLogLevelServiceModule(webServer);
+ private final WebServer webServer = mock(WebServer.class);
+ private final ChangeLogLevelServiceModule underTest = new ChangeLogLevelServiceModule(webServer);
@Test
public void provide_returns_ChangeLogLevelClusterService_if_cluster_not_on_SonarCloud() {
when(webServer.isStandalone()).thenReturn(false);
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- Collection<ComponentAdapter<?>> adapters = container.getPicoContainer().getComponentAdapters();
- assertThat(adapters)
- .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 1)
- .extracting(ComponentAdapter::getComponentKey)
- .contains(ChangeLogLevelClusterService.class)
- .doesNotContain(ChangeLogLevelStandaloneService.class);
+ assertThat(container.getAddedObjects()).containsOnly(ChangeLogLevelClusterService.class);
}
@Test
public void provide_returns_ChangeLogLevelStandaloneService_if_SQ_standalone() {
when(webServer.isStandalone()).thenReturn(true);
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
verifyInStandaloneSQ(container);
}
- private void verifyInStandaloneSQ(ComponentContainer container) {
- Collection<ComponentAdapter<?>> adapters = container.getPicoContainer().getComponentAdapters();
- assertThat(adapters)
- .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 1)
- .extracting(ComponentAdapter::getComponentKey)
- .contains(ChangeLogLevelStandaloneService.class)
- .doesNotContain(ChangeLogLevelClusterService.class);
+ private void verifyInStandaloneSQ(ListContainer container) {
+ assertThat(container.getAddedObjects()).containsOnly(ChangeLogLevelStandaloneService.class);
}
-
}
*/
package org.sonar.server.platform.ws;
-import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import org.junit.Test;
-import org.picocontainer.ComponentAdapter;
-import org.sonar.core.platform.ComponentContainer;
import org.sonar.server.health.AppNodeClusterCheck;
import org.sonar.server.health.CeStatusNodeCheck;
import org.sonar.server.health.ClusterHealthCheck;
import org.sonar.server.health.HealthCheckerImpl;
import org.sonar.server.health.NodeHealthCheck;
import org.sonar.server.health.WebServerStatusNodeCheck;
+import org.sonar.core.platform.ListContainer;
import org.sonar.server.platform.WebServer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
public class HealthCheckerModuleTest {
- private WebServer webServer = mock(WebServer.class);
- private HealthCheckerModule underTest = new HealthCheckerModule(webServer);
+ private final WebServer webServer = mock(WebServer.class);
+ private final HealthCheckerModule underTest = new HealthCheckerModule(webServer);
@Test
public void verify_HealthChecker() {
boolean standalone = new Random().nextBoolean();
when(webServer.isStandalone()).thenReturn(standalone);
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- assertThat(classesAddedToContainer(container))
+ assertThat(container.getAddedObjects())
.describedAs("Verifying action and HealthChecker with standalone=%s", standalone)
.contains(HealthCheckerImpl.class)
.doesNotContain(HealthActionSupport.class)
@Test
public void verify_installed_NodeHealthChecks_implementations_when_standalone() {
when(webServer.isStandalone()).thenReturn(true);
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- List<Class<?>> checks = classesAddedToContainer(container).stream().filter(NodeHealthCheck.class::isAssignableFrom).collect(Collectors.toList());
- assertThat(checks)
- .hasSize(4)
- .contains(WebServerStatusNodeCheck.class)
- .contains(DbConnectionNodeCheck.class)
- .contains(EsStatusNodeCheck.class)
- .contains(CeStatusNodeCheck.class);
+ List<Class<?>> checks = container.getAddedObjects().stream()
+ .filter(o -> o instanceof Class)
+ .map(o -> (Class<?>) o)
+ .filter(NodeHealthCheck.class::isAssignableFrom).collect(Collectors.toList());
+ assertThat(checks).containsOnly(WebServerStatusNodeCheck.class, DbConnectionNodeCheck.class, EsStatusNodeCheck.class, CeStatusNodeCheck.class);
}
@Test
public void verify_installed_NodeHealthChecks_implementations_when_clustered() {
when(webServer.isStandalone()).thenReturn(false);
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- List<Class<?>> checks = classesAddedToContainer(container).stream().filter(NodeHealthCheck.class::isAssignableFrom).collect(Collectors.toList());
- assertThat(checks)
- .hasSize(3)
- .contains(WebServerStatusNodeCheck.class)
- .contains(DbConnectionNodeCheck.class)
- .contains(CeStatusNodeCheck.class)
- .doesNotContain(EsStatusNodeCheck.class);
+ List<Class<?>> checks = container.getAddedObjects().stream()
+ .filter(o -> o instanceof Class)
+ .map(o -> (Class<?>) o)
+ .filter(NodeHealthCheck.class::isAssignableFrom).collect(Collectors.toList());
+ assertThat(checks).containsOnly(WebServerStatusNodeCheck.class, DbConnectionNodeCheck.class, CeStatusNodeCheck.class);
}
@Test
public void verify_installed_ClusterHealthChecks_implementations_in_standalone() {
when(webServer.isStandalone()).thenReturn(true);
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- List<Class<?>> checks = classesAddedToContainer(container).stream().filter(ClusterHealthCheck.class::isAssignableFrom).collect(Collectors.toList());
+ List<Class<?>> checks = container.getAddedObjects().stream()
+ .filter(o -> o instanceof Class<?>)
+ .map(o -> (Class<?>) o)
+ .filter(ClusterHealthCheck.class::isAssignableFrom).collect(Collectors.toList());
assertThat(checks).isEmpty();
}
@Test
public void verify_installed_ClusterHealthChecks_implementations_in_clustering() {
when(webServer.isStandalone()).thenReturn(false);
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- List<Class<?>> checks = classesAddedToContainer(container).stream().filter(ClusterHealthCheck.class::isAssignableFrom).collect(Collectors.toList());
- assertThat(checks)
- .hasSize(2)
- .contains(EsStatusClusterCheck.class)
- .contains(AppNodeClusterCheck.class);
- }
-
- private List<Class<?>> classesAddedToContainer(ComponentContainer container) {
- Collection<ComponentAdapter<?>> componentAdapters = container.getPicoContainer().getComponentAdapters();
- return componentAdapters.stream().map(ComponentAdapter::getComponentImplementation).collect(Collectors.toList());
+ List<Class<?>> checks = container.getAddedObjects().stream()
+ .filter(o -> o instanceof Class<?>)
+ .map(o -> (Class<?>) o)
+ .filter(ClusterHealthCheck.class::isAssignableFrom).collect(Collectors.toList());
+ assertThat(checks).containsOnly(EsStatusClusterCheck.class, AppNodeClusterCheck.class);
}
}
private final EsStatusNodeCheck esStatusNodeCheck = mock(EsStatusNodeCheck.class);
LivenessCheckerImpl underTest = new LivenessCheckerImpl(dbConnectionNodeCheck, webServerStatusNodeCheck, ceStatusNodeCheck, esStatusNodeCheck);
- LivenessCheckerImpl underTestDCE = new LivenessCheckerImpl(dbConnectionNodeCheck, webServerStatusNodeCheck, ceStatusNodeCheck);
+ LivenessCheckerImpl underTestDCE = new LivenessCheckerImpl(dbConnectionNodeCheck, webServerStatusNodeCheck, ceStatusNodeCheck, null);
@Test
public void fail_when_db_connection_check_fail() {
*/
package org.sonar.server.platform.ws;
-import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
-import org.picocontainer.ComponentAdapter;
-import org.sonar.core.platform.ComponentContainer;
import org.sonar.server.health.DbConnectionNodeCheck;
import org.sonar.server.health.EsStatusNodeCheck;
import org.sonar.server.health.HealthCheckerImpl;
import org.sonar.server.health.NodeHealthCheck;
import org.sonar.server.health.WebServerSafemodeNodeCheck;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class SafeModeHealthCheckerModuleTest {
- private SafeModeHealthCheckerModule underTest = new SafeModeHealthCheckerModule();
+ private final SafeModeHealthCheckerModule underTest = new SafeModeHealthCheckerModule();
@Test
public void verify_HealthChecker() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- assertThat(classesAddedToContainer(container))
+ assertThat(container.getAddedObjects())
.contains(HealthCheckerImpl.class)
.doesNotContain(HealthActionSupport.class)
.doesNotContain(SafeModeHealthAction.class)
@Test
public void verify_installed_HealthChecks_implementations() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- List<Class<?>> checks = classesAddedToContainer(container).stream().filter(NodeHealthCheck.class::isAssignableFrom).collect(Collectors.toList());
- assertThat(checks)
- .hasSize(3)
- .contains(WebServerSafemodeNodeCheck.class)
- .contains(DbConnectionNodeCheck.class)
- .contains(EsStatusNodeCheck.class);
+ List<Class<?>> checks = container.getAddedObjects().stream()
+ .filter(o -> o instanceof Class)
+ .map(o -> (Class<?>) o)
+ .filter(NodeHealthCheck.class::isAssignableFrom)
+ .collect(Collectors.toList());
+ assertThat(checks).containsOnly(WebServerSafemodeNodeCheck.class, DbConnectionNodeCheck.class, EsStatusNodeCheck.class);
}
-
- private List<Class<?>> classesAddedToContainer(ComponentContainer container) {
- Collection<ComponentAdapter<?>> componentAdapters = container.getPicoContainer().getComponentAdapters();
- return componentAdapters.stream().map(ComponentAdapter::getComponentImplementation).collect(Collectors.toList());
- }
-
}
package org.sonar.server.platform.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class SafemodeSystemWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new SafemodeSystemWsModule().configure(container);
- assertThat(container.size()).isPositive();
+ assertThat(container.getAddedObjects()).isNotEmpty();
}
-
}
package org.sonar.server.platform.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class SystemWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new SystemWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 15);
+ assertThat(container.getAddedObjects()).hasSize(15);
}
-
-
}
package org.sonar.server.project.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class ProjectsWsModuleTest {
-
@Test
public void verify_count_of_added_components_on_SonarQube() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new ProjectsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 11);
+ assertThat(container.getAddedObjects()).hasSize(11);
}
-
}
package org.sonar.server.projectanalysis.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class ProjectAnalysisWsModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new ProjectAnalysisWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 8);
+ assertThat(container.getAddedObjects()).hasSize(8);
}
}
package org.sonar.server.projectlink.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class ProjectLinksWsModuleTest {
-
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new ProjectLinksModule().configure(container);
- assertThat(container.size()).isEqualTo(2 + 4);
+ assertThat(container.getAddedObjects()).hasSize(4);
}
}
package org.sonar.server.projecttag.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class ProjectTagsWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new ProjectTagsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 4);
+ assertThat(container.getAddedObjects()).hasSize(4);
}
}
package org.sonar.server.qualitygate;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class QualityGateModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new QualityGateModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 4);
+ assertThat(container.getAddedObjects()).hasSize(4);
}
}
package org.sonar.server.qualitygate.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class QualityGateWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new QualityGateWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 23);
+ assertThat(container.getAddedObjects()).hasSize(23);
}
-
}
package org.sonar.server.qualityprofile.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class QProfilesWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new QProfilesWsModule().configure(container);
- assertThat(container.size()).isEqualTo(31 + 2);
+ assertThat(container.getAddedObjects()).hasSize(31);
}
}
package org.sonar.server.root.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class RootsWsModuleTest {
private RootWsModule underTest = new RootWsModule();
@Test
public void verify_number_of_components_added_by_module() {
- ComponentContainer container = new ComponentContainer();
-
+ ListContainer container = new ListContainer();
underTest.configure(container);
-
- assertThat(container.getPicoContainer().getComponentAdapters())
- .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 4);
+ assertThat(container.getAddedObjects()).hasSize(4);
}
}
package org.sonar.server.setting.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class SettingsWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new SettingsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(11 + 2);
+ assertThat(container.getAddedObjects()).hasSize(11);
}
}
package org.sonar.server.source.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import org.sonar.server.ws.WsAction;
import static org.assertj.core.api.Assertions.assertThat;
public class SourceWsModuleTest {
- private SourceWsModule underTest = new SourceWsModule();
+ private final SourceWsModule underTest = new SourceWsModule();
@Test
public void verify_count_of_actions() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- assertThat(container.getPicoContainer().getComponentAdapters(WsAction.class)).hasSize(6);
+ assertThat(container.getAddedObjects().stream().filter(o -> o instanceof Class && WsAction.class.isAssignableFrom((Class<?>) o)))
+ .hasSize(6);
}
-
}
@Test
public void return_empty_if_no_analytics_plugin() {
- assertThat(new WebAnalyticsLoaderImpl().getUrlPathToJs()).isEmpty();
+ assertThat(new WebAnalyticsLoaderImpl(null).getUrlPathToJs()).isEmpty();
assertThat(new WebAnalyticsLoaderImpl(new WebAnalytics[0]).getUrlPathToJs()).isEmpty();
}
package org.sonar.server.ui.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class NavigationWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new NavigationWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 5);
+ assertThat(container.getAddedObjects()).hasSize(5);
}
}
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbTester;
+import org.sonar.db.audit.NoOpAuditPersister;
import org.sonar.db.user.UserDto;
import org.sonar.server.authentication.CredentialsLocalAuthentication;
import org.sonar.server.es.EsTester;
private final UserUpdater userUpdater = new UserUpdater(mock(NewUserNotifier.class), db.getDbClient(),
new UserIndexer(db.getDbClient(), es.client()), new DefaultGroupFinder(db.getDbClient()),
- new MapSettings().asConfig(), null, localAuthentication);
+ new MapSettings().asConfig(), new NoOpAuditPersister(), localAuthentication);
private final WsActionTester tester = new WsActionTester(new ChangePasswordAction(db.getDbClient(), userUpdater, userSessionRule, localAuthentication));
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
+import org.sonar.db.audit.NoOpAuditPersister;
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.authentication.CredentialsLocalAuthentication;
private GroupDto defaultGroup;
private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig());
private final WsActionTester tester = new WsActionTester(new CreateAction(db.getDbClient(), new UserUpdater(mock(NewUserNotifier.class),
- db.getDbClient(), userIndexer, new DefaultGroupFinder(db.getDbClient()), settings.asConfig(), null, localAuthentication), userSessionRule));
+ db.getDbClient(), userIndexer, new DefaultGroupFinder(db.getDbClient()), settings.asConfig(), new NoOpAuditPersister(), localAuthentication), userSessionRule));
@Before
public void setUp() {
package org.sonar.server.user.ws;
import org.junit.Test;
-import org.sonar.api.config.internal.ConfigurationBridge;
-import org.sonar.api.config.internal.MapSettings;
-import org.sonar.core.platform.ComponentContainer;
-import org.sonar.process.ProcessProperties;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class UsersWsModuleTest {
- private MapSettings settings = new MapSettings();
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
- new UsersWsModule(new ConfigurationBridge(settings)).configure(container);
- assertThat(container.size()).isEqualTo(2 + 16);
- }
-
- @Test
- public void verify_count_of_added_components_in_sonarcloud() {
- settings.setProperty(ProcessProperties.Property.SONARCLOUD_ENABLED.getKey(), true);
-
- ComponentContainer container = new ComponentContainer();
- new UsersWsModule(new ConfigurationBridge(settings)).configure(container);
- assertThat(container.size()).isEqualTo(2 + 17);
+ ListContainer container = new ListContainer();
+ new UsersWsModule().configure(container);
+ assertThat(container.getAddedObjects()).hasSize(16);
}
}
package org.sonar.server.usergroups.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class UserGroupsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new UserGroupsModule().configure(container);
- assertThat(container.size()).isEqualTo(11);
+ assertThat(container.getAddedObjects()).hasSize(9);
}
}
package org.sonar.server.usertoken.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import org.sonar.server.usertoken.UserTokenModule;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class UserTokenWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new UserTokenModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
+ assertThat(container.getAddedObjects()).hasSize(2);
}
-
-
}
package org.sonar.server.webhook.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class WebhooksWsModuleTest {
-
- private WebhooksWsModule underTest = new WebhooksWsModule();
+ private final WebhooksWsModule underTest = new WebhooksWsModule();
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.configure(container);
- assertThat(container.size()).isNotZero();
+ assertThat(container.getAddedObjects()).isNotEmpty();
}
-
}
package org.sonar.server.ws.ws;
import org.junit.Test;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
public class WebServicesWsModuleTest {
@Test
public void verify_count_of_added_components() {
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
new WebServicesWsModule().configure(container);
- assertThat(container.size()).isEqualTo(3 + 2);
+ assertThat(container.getAddedObjects()).hasSize(3);
}
}
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.catalina.connector.ClientAbortException;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.impl.ws.ValidatingRequest;
import org.sonar.api.server.ServerSide;
import org.sonar.api.server.ws.LocalConnector;
*/
package org.sonar.server.platform;
-import com.google.common.collect.Lists;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
-import java.util.function.Supplier;
import javax.annotation.Nullable;
import javax.servlet.ServletContext;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ExtensionContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.server.app.ProcessCommandWrapper;
import org.sonar.server.platform.db.migration.version.DatabaseVersion;
import org.sonar.server.platform.platformlevel.PlatformLevel;
private static final PlatformImpl INSTANCE = new PlatformImpl();
- private final Supplier<AutoStarter> autoStarterSupplier;
private AutoStarter autoStarter = null;
private Properties properties;
private ServletContext servletContext;
private PlatformLevel currentLevel;
private boolean dbConnected = false;
private boolean started = false;
- private final List<Object> level4AddedComponents = Lists.newArrayList();
+ private final List<Object> level4AddedComponents = new ArrayList<>();
private final Profiler profiler = Profiler.createIfTrace(Loggers.get(PlatformImpl.class));
- private PlatformImpl() {
- this.autoStarterSupplier = () -> {
- ProcessCommandWrapper processCommandWrapper = getContainer().getComponentByType(ProcessCommandWrapper.class);
- return new AsynchronousAutoStarter(processCommandWrapper);
- };
- }
-
- protected PlatformImpl(Supplier<AutoStarter> autoStarterSupplier) {
- this.autoStarterSupplier = autoStarterSupplier;
- }
-
public static PlatformImpl getInstance() {
return INSTANCE;
}
}
}
- // Platform is injected in Pico, so do not rename this method "start"
@Override
public void doStart() {
- doStart(Startup.ALL);
- }
-
- protected void doStart(Startup startup) {
if (started && !isInSafeMode()) {
return;
}
if (dbRequiresMigration()) {
LOGGER.info("Database needs to be migrated. Please refer to https://docs.sonarqube.org/latest/setup/upgrading");
} else {
- this.autoStarter = autoStarterSupplier.get();
+ this.autoStarter = createAutoStarter();
this.autoStarter.execute(new AutoStarterRunnable(autoStarter) {
@Override
public void doRun() {
}
runIfNotAborted(PlatformImpl.this::startLevel34Containers);
- runIfNotAborted(() -> executeStartupTasks(startup));
+ runIfNotAborted(PlatformImpl.this::executeStartupTasks);
// switch current container last to avoid giving access to a partially initialized container
runIfNotAborted(() -> {
currentLevel = level4;
}
}
+ private AutoStarter createAutoStarter() {
+ ProcessCommandWrapper processCommandWrapper = getContainer().getComponentByType(ProcessCommandWrapper.class);
+ return new AsynchronousAutoStarter(processCommandWrapper);
+ }
+
private boolean dbRequiresMigration() {
return getDatabaseStatus() != DatabaseVersion.Status.UP_TO_DATE;
}
level4 = start(new PlatformLevel4(level3, level4AddedComponents));
}
- public void executeStartupTasks() {
- executeStartupTasks(Startup.ALL);
- }
-
- private void executeStartupTasks(Startup startup) {
- if (startup.ordinal() >= Startup.ALL.ordinal()) {
- new PlatformLevelStartup(level4)
- .configure()
- .start()
- .stop()
- .destroy();
- }
+ private void executeStartupTasks() {
+ new PlatformLevelStartup(level4)
+ .configure()
+ .start()
+ .stop();
}
private void startSafeModeContainer() {
* Stops level 2, 3 and 4 containers cleanly if they exists.
* Call this method before {@link #startLevel1Container()} to avoid duplicate attempt to stop safemode container
* components (since calling stop on a container calls stop on its children too, see
- * {@link ComponentContainer#stopComponents()}).
+ * {@link SpringComponentContainer#stopComponents()}).
*/
private void stopLevel234Containers() {
if (level2 != null) {
* Stops safemode container cleanly if it exists.
* Call this method before {@link #stopLevel234Containers()} and {@link #stopLevel1Container()} to avoid duplicate
* attempt to stop safemode container components (since calling stop on a container calls stops on its children too,
- * see {@link ComponentContainer#stopComponents()}).
+ * see {@link SpringComponentContainer#stopComponents()}).
*/
private void stopSafeModeContainer() {
if (levelSafeMode != null) {
return version.getStatus();
}
- // Do not rename "stop"
public void doStop() {
try {
stopAutoStarter();
}
@Override
- public ComponentContainer getContainer() {
+ public ExtensionContainer getContainer() {
return currentLevel.getContainer();
}
- public Object getComponent(Object key) {
- return getContainer().getComponentByKey(key);
- }
-
- public enum Startup {
- NO_STARTUP_TASKS, ALL
- }
-
public interface AutoStarter {
/**
* Let the autostarted execute the provided code.
package org.sonar.server.platform.platformlevel;
import java.util.Collection;
-import java.util.List;
import java.util.Optional;
-import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.sonar.core.platform.ComponentContainer;
-import org.sonar.core.platform.Module;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.server.platform.WebServer;
import static com.google.common.base.Preconditions.checkNotNull;
public abstract class PlatformLevel {
private final String name;
@Nullable
- private final PlatformLevel parent;
- private final ComponentContainer container;
+ protected final PlatformLevel parent;
+ private final SpringComponentContainer container;
private AddIfStartupLeader addIfStartupLeader;
private AddIfCluster addIfCluster;
private AddIfStandalone addIfStandalone;
- public PlatformLevel(String name) {
+ protected PlatformLevel(String name) {
this.name = name;
this.parent = null;
this.container = createContainer(null);
}
- public PlatformLevel(String name, @Nonnull PlatformLevel parent) {
+ protected PlatformLevel(String name, PlatformLevel parent) {
this.name = checkNotNull(name);
this.parent = checkNotNull(parent);
- this.container = createContainer(parent.container);
+ this.container = createContainer(parent.getContainer());
}
- public ComponentContainer getContainer() {
+ public SpringComponentContainer getContainer() {
return container;
}
/**
* Intended to be override by subclasses if needed
*/
- protected ComponentContainer createContainer(@Nullable ComponentContainer parent) {
+ protected SpringComponentContainer createContainer(@Nullable SpringComponentContainer parent) {
if (parent == null) {
- return new ComponentContainer();
+ return new SpringComponentContainer();
}
return parent.createChild();
}
public PlatformLevel configure() {
configureLevel();
-
- List<Module> modules = container.getComponentsByType(Module.class);
- for (Module module : modules) {
- module.configure(container);
- }
-
return this;
}
*/
public PlatformLevel start() {
container.startComponents();
-
return this;
}
*/
public PlatformLevel stop() {
container.stopComponents();
-
- return this;
- }
-
- /**
- * Intended to be override by subclasses if needed
- */
- public PlatformLevel destroy() {
- if (parent != null) {
- parent.container.removeChild(container);
- }
return this;
}
protected <T> T get(Class<T> tClass) {
- return requireNonNull(container.getComponentByType(tClass));
- }
-
- protected <T> List<T> getAll(Class<T> tClass) {
- return container.getComponentsByType(tClass);
+ return container.getComponentByType(tClass);
}
protected <T> Optional<T> getOptional(Class<T> tClass) {
- return Optional.ofNullable(container.getComponentByType(tClass));
+ return container.getOptionalComponentByType(tClass);
}
protected void add(Object... objects) {
for (Object object : objects) {
if (object != null) {
- container.addComponent(object, true);
+ container.add(object);
}
}
}
}
protected WebServer getWebServer() {
- return getOptional(WebServer.class)
- .orElseThrow(() -> new IllegalStateException("WebServer not available in Pico yet"));
+ return Optional.ofNullable(parent)
+ .flatMap(p -> p.getOptional(WebServer.class))
+ .or(() -> getOptional(WebServer.class))
+ .orElseThrow(() -> new IllegalStateException("WebServer not available in the container"));
}
protected abstract class AddIf {
import java.time.Clock;
import java.util.Properties;
-import javax.annotation.Nullable;
import org.sonar.api.SonarEdition;
import org.sonar.api.SonarQubeSide;
import org.sonar.api.SonarQubeVersion;
import org.sonar.api.internal.SonarRuntimeImpl;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.Version;
-import org.sonar.db.audit.AuditPersister;
-import org.sonar.db.audit.NoOpAuditPersister;
-import org.sonar.server.issue.index.IssueIndexSyncProgressChecker;
-import org.sonar.server.platform.DockerSupportImpl;
-import org.sonar.server.util.GlobalLockManagerImpl;
-import org.sonar.server.util.Paths2Impl;
-import org.sonar.server.util.TempFolderCleaner;
import org.sonar.core.config.CorePropertyDefinitions;
import org.sonar.core.extension.CoreExtensionRepositoryImpl;
import org.sonar.core.extension.CoreExtensionsLoader;
import org.sonar.db.DbClient;
import org.sonar.db.DefaultDatabase;
import org.sonar.db.MyBatis;
+import org.sonar.db.audit.AuditPersister;
+import org.sonar.db.audit.NoOpAuditPersister;
import org.sonar.db.purge.PurgeProfiler;
import org.sonar.process.NetworkUtilsImpl;
import org.sonar.process.logging.LogbackHelper;
import org.sonar.server.config.ConfigurationProvider;
import org.sonar.server.es.EsModule;
import org.sonar.server.issue.index.IssueIndex;
+import org.sonar.server.issue.index.IssueIndexSyncProgressChecker;
import org.sonar.server.permission.index.WebAuthorizationTypeSupport;
+import org.sonar.server.platform.DockerSupportImpl;
import org.sonar.server.platform.LogServerVersion;
import org.sonar.server.platform.Platform;
import org.sonar.server.platform.ServerFileSystemImpl;
import org.sonar.server.setting.ThreadLocalSettings;
import org.sonar.server.user.SystemPasscodeImpl;
import org.sonar.server.user.ThreadLocalUserSession;
+import org.sonar.server.util.GlobalLockManagerImpl;
import org.sonar.server.util.OkHttpClientProvider;
+import org.sonar.server.util.Paths2Impl;
+import org.sonar.server.util.TempFolderCleaner;
import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
import static org.sonar.core.extension.PlatformLevelPredicates.hasPlatformLevel;
public class PlatformLevel1 extends PlatformLevel {
private final Platform platform;
private final Properties properties;
- @Nullable
private final Object[] extraRootComponents;
public PlatformLevel1(Platform platform, Properties properties, Object... extraRootComponents) {
new SonarQubeVersion(apiVersion),
SonarRuntimeImpl.forSonarQube(apiVersion, SonarQubeSide.SERVER, edition),
ThreadLocalSettings.class,
- new ConfigurationProvider(),
+ ConfigurationProvider.class,
LogServerVersion.class,
ProcessCommandWrapperImpl.class,
RestartFlagHolderImpl.class,
// DB
DBSessionsImpl.class,
DbClient.class,
- DaoModule.class,
+ new DaoModule(),
// Elasticsearch
WebAuthorizationTypeSupport.class,
- EsModule.class,
+ new EsModule(),
// rules/qprofiles
RuleIndex.class,
@Override
public PlatformLevel start() {
+ PlatformLevel start = super.start();
get(CoreExtensionsLoader.class)
.load();
get(WebCoreExtensionsInstaller.class)
add(NoOpAuditPersister.class);
}
- return super.start();
+ return start;
}
}
import org.sonar.api.utils.Durations;
import org.sonar.core.extension.CoreExtensionsInstaller;
-import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.PluginClassLoader;
import org.sonar.core.platform.PluginClassloaderFactory;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.server.es.MigrationEsClientImpl;
import org.sonar.server.l18n.ServerI18n;
import org.sonar.server.platform.DatabaseServerCompatibility;
import org.sonar.server.platform.db.migration.DatabaseMigrationStateImpl;
import org.sonar.server.platform.db.migration.MigrationConfigurationModule;
import org.sonar.server.platform.db.migration.charset.DatabaseCharsetChecker;
-import org.sonar.server.platform.db.migration.history.MigrationHistoryTable;
-import org.sonar.server.platform.db.migration.history.MigrationHistoryTableImpl;
import org.sonar.server.platform.db.migration.version.DatabaseVersion;
import org.sonar.server.platform.web.WebPagesCache;
import org.sonar.server.plugins.InstalledPluginReferentialFactory;
@Override
protected void configureLevel() {
add(
- MigrationConfigurationModule.class,
+ new MigrationConfigurationModule(),
DatabaseVersion.class,
DatabaseServerCompatibility.class,
MigrationEsClientImpl.class,
// Migration state must be kept at level2 to survive moving in and then out of safe mode
// ExecutorService must be kept at level2 because stopping it when stopping safe mode level causes error making SQ fail
add(
- MigrationHistoryTableImpl.class,
DatabaseMigrationStateImpl.class,
DatabaseMigrationExecutorServiceImpl.class);
@Override
public PlatformLevel start() {
- // ensuring the HistoryTable exists must be the first thing done when this level is started
- getOptional(MigrationHistoryTable.class).ifPresent(MigrationHistoryTable::start);
-
- ComponentContainer container = getContainer();
- CoreExtensionsInstaller coreExtensionsInstaller = get(WebCoreExtensionsInstaller.class);
+ SpringComponentContainer container = getContainer();
+ CoreExtensionsInstaller coreExtensionsInstaller = parent.get(WebCoreExtensionsInstaller.class);
coreExtensionsInstaller.install(container, hasPlatformLevel(2), noAdditionalSideFilter());
return super.start();
import org.sonar.api.utils.UriReader;
import org.sonar.core.extension.CoreExtensionsInstaller;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.core.util.DefaultHttpDownloader;
import org.sonar.server.async.AsyncExecutionModule;
import org.sonar.server.platform.ServerImpl;
DetectPluginChange.class);
add(
NoopDatabaseMigrationImpl.class,
- ServerIdModule.class,
+ new ServerIdModule(),
ServerImpl.class,
DatabaseSettingLoader.class,
DatabaseSettingsEnabler.class,
UriReader.class,
DefaultHttpDownloader.class,
- AsyncExecutionModule.class);
+ new AsyncExecutionModule());
}
@Override
public PlatformLevel start() {
- ComponentContainer container = getContainer();
- CoreExtensionsInstaller coreExtensionsInstaller = get(WebCoreExtensionsInstaller.class);
+ SpringComponentContainer container = getContainer();
+ CoreExtensionsInstaller coreExtensionsInstaller = parent.get(WebCoreExtensionsInstaller.class);
coreExtensionsInstaller.install(container, hasPlatformLevel(3), noAdditionalSideFilter());
return super.start();
import org.sonar.alm.client.gitlab.GitlabHttpClient;
import org.sonar.api.profiles.XMLProfileParser;
import org.sonar.api.profiles.XMLProfileSerializer;
-import org.sonar.api.resources.Languages;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.rules.AnnotationRuleParser;
import org.sonar.api.server.rule.RulesDefinitionXmlLoader;
import org.sonar.ce.task.projectexport.taskprocessor.ProjectExportTaskProcessor;
import org.sonar.core.component.DefaultResourceTypes;
import org.sonar.core.extension.CoreExtensionsInstaller;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.language.LanguagesProvider;
import org.sonar.core.platform.PlatformEditionProvider;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.server.almintegration.ws.AlmIntegrationsWSModule;
import org.sonar.server.almintegration.ws.CredentialsEncoderHelper;
import org.sonar.server.almintegration.ws.ImportHelper;
MetadataIndexImpl.class,
EsDbCompatibilityImpl.class);
- addIfCluster(NodeHealthModule.class);
+ addIfCluster(new NodeHealthModule());
addIfCluster(DistributedRuleActivatorEventsDistributor.class);
addIfStandalone(StandaloneRuleActivatorEventsDistributor.class);
ServerWs.class,
IndexDefinitions.class,
WebAnalyticsLoaderImpl.class,
- MonitoringWsModule.class,
+ new MonitoringWsModule(),
// batch
- BatchWsModule.class,
+ new BatchWsModule(),
// update center
- UpdateCenterModule.class,
+ new UpdateCenterModule(),
// quality profile
BuiltInQProfileRepositoryImpl.class,
QProfileBackuperImpl.class,
QProfileParser.class,
QProfileResetImpl.class,
- QProfilesWsModule.class,
+ new QProfilesWsModule(),
// rule
RuleIndexDefinition.class,
org.sonar.server.rule.ws.AppAction.class,
// languages
- Languages.class,
+ LanguagesProvider.class,
LanguageWs.class,
LanguageValidation.class,
org.sonar.server.language.ws.ListAction.class,
// measure
- MetricsWsModule.class,
- MeasuresWsModule.class,
+ new MetricsWsModule(),
+ new MeasuresWsModule(),
MetricFinder.class,
UnanalyzedLanguageMetrics.class,
- QualityGateModule.class,
- ProjectsInWarningModule.class,
- QualityGateWsModule.class,
+ new QualityGateModule(),
+ new ProjectsInWarningModule(),
+ new QualityGateWsModule(),
// web services
WebServiceEngine.class,
- WebServicesWsModule.class,
+ new WebServicesWsModule(),
SonarLintConnectionFilter.class,
WebServiceFilter.class,
WebServiceReroutingFilter.class,
org.sonar.server.platform.ws.IndexAction.class,
// authentication
- AuthenticationModule.class,
- AuthenticationWsModule.class,
- BitbucketModule.class,
- GitHubModule.class,
- GitLabModule.class,
- LdapModule.class,
- SamlModule.class,
+ new AuthenticationModule(),
+ new AuthenticationWsModule(),
+ new BitbucketModule(),
+ new GitHubModule(),
+ new GitLabModule(),
+ new LdapModule(),
+ new SamlModule(),
DefaultAdminCredentialsVerifierImpl.class,
DefaultAdminCredentialsVerifierNotificationTemplate.class,
DefaultAdminCredentialsVerifierNotificationHandler.class,
UserIndexer.class,
UserIndex.class,
UserUpdater.class,
- UsersWsModule.class,
- UserTokenModule.class,
- UserTokenWsModule.class,
+ new UsersWsModule(),
+ new UserTokenModule(),
+ new UserTokenWsModule(),
// groups
- UserGroupsModule.class,
+ new UserGroupsModule(),
DefaultGroupFinder.class,
// permissions
DefaultTemplatesResolverImpl.class,
- PermissionsWsModule.class,
+ new PermissionsWsModule(),
PermissionTemplateService.class,
PermissionUpdater.class,
UserPermissionChanger.class,
GroupPermissionChanger.class,
// components
- BranchWsModule.class,
- PullRequestWsModule.class,
- ProjectsWsModule.class,
- ProjectsEsModule.class,
- ProjectTagsWsModule.class,
- ComponentsWsModule.class,
+ new BranchWsModule(),
+ new PullRequestWsModule(),
+ new ProjectsWsModule(),
+ new ProjectsEsModule(),
+ new ProjectTagsWsModule(),
+ new ComponentsWsModule(),
ComponentService.class,
ComponentUpdater.class,
ComponentFinder.class,
ComponentIndexDefinition.class,
ComponentIndex.class,
ComponentIndexer.class,
- LiveMeasureModule.class,
+ new LiveMeasureModule(),
ComponentViewerJsonWriter.class,
- DevelopersWsModule.class,
+ new DevelopersWsModule(),
- FavoriteModule.class,
- FavoriteWsModule.class,
+ new FavoriteModule(),
+ new FavoriteWsModule(),
// views
ViewIndexDefinition.class,
IssueIndexer.class,
IssueIteratorFactory.class,
PermissionIndexer.class,
- IssueWsModule.class,
+ new IssueWsModule(),
NewIssuesEmailTemplate.class,
MyNewIssuesEmailTemplate.class,
- IssuesChangesNotificationModule.class,
+ new IssuesChangesNotificationModule(),
NewIssuesNotificationHandler.class,
NewIssuesNotificationHandler.newMetadata(),
MyNewIssuesNotificationHandler.class,
IssueChangePostProcessorImpl.class,
// hotspots
- HotspotsWsModule.class,
+ new HotspotsWsModule(),
// source
- SourceWsModule.class,
+ new SourceWsModule(),
// Duplications
DuplicationsParser.class,
BuiltInQPChangeNotificationTemplate.class,
BuiltInQPChangeNotificationHandler.class,
- NotificationModule.class,
- NotificationWsModule.class,
- EmailsWsModule.class,
+ new NotificationModule(),
+ new NotificationWsModule(),
+ new EmailsWsModule(),
// Settings
ProjectConfigurationLoaderImpl.class,
PersistentSettings.class,
- SettingsWsModule.class,
+ new SettingsWsModule(),
- TypeValidationModule.class,
+ new TypeValidationModule(),
// New Code Periods
- NewCodePeriodsWsModule.class,
+ new NewCodePeriodsWsModule(),
// Project Links
- ProjectLinksModule.class,
+ new ProjectLinksModule(),
// Project Analyses
- ProjectAnalysisWsModule.class,
+ new ProjectAnalysisWsModule(),
// System
ServerLogging.class,
- ChangeLogLevelServiceModule.class,
- HealthCheckerModule.class,
- SystemWsModule.class,
+ new ChangeLogLevelServiceModule(getWebServer()),
+ new HealthCheckerModule(getWebServer()),
+ new SystemWsModule(),
// Plugins WS
PluginUpdateAggregator.class,
BitbucketCloudRestClient.class,
GitlabHttpClient.class,
AzureDevOpsHttpClient.class,
- AlmIntegrationsWSModule.class,
+ new AlmIntegrationsWSModule(),
BitbucketCloudValidator.class,
BitbucketServerSettingsValidator.class,
GithubGlobalSettingsValidator.class,
AzureDevOpsValidator.class,
// ALM settings
- AlmSettingsWsModule.class,
+ new AlmSettingsWsModule(),
// Project export
- ProjectExportWsModule.class,
+ new ProjectExportWsModule(),
// Branch
BranchFeatureProxyImpl.class,
// Project badges
- ProjectBadgesWsModule.class,
+ new ProjectBadgesWsModule(),
// Core Extensions
CoreExtensionBootstraper.class,
MultipleAlmFeatureProvider.class,
// ServerPush endpoints
- ServerPushWsModule.class,
+ new ServerPushWsModule(),
// Compute engine (must be after Views and Developer Cockpit)
- ReportAnalysisFailureNotificationModule.class,
- CeModule.class,
- CeWsModule.class,
+ new ReportAnalysisFailureNotificationModule(),
+ new CeModule(),
+ new CeWsModule(),
ReportTaskProcessor.class,
IssueSyncTaskProcessor.class,
AuditPurgeTaskProcessor.class,
InternalPropertiesImpl.class,
// UI
- NavigationWsModule.class,
+ new NavigationWsModule(),
// root
- RootWsModule.class,
+ new RootWsModule(),
// webhooks
WebhookQGChangeEventListener.class,
- WebhookModule.class,
- WebhooksWsModule.class,
+ new WebhookModule(),
+ new WebhooksWsModule(),
// Http Request ID
- HttpRequestIdModule.class,
+ new HttpRequestIdModule(),
RecoveryIndexer.class,
ProjectIndexersImpl.class,
);
// system info
- add(SystemInfoWriterModule.class);
+ add(new SystemInfoWriterModule(getWebServer()));
addAll(level4AddedComponents);
}
@Override
public PlatformLevel start() {
- ComponentContainer container = getContainer();
- CoreExtensionsInstaller coreExtensionsInstaller = get(WebCoreExtensionsInstaller.class);
+ SpringComponentContainer container = getContainer();
+ CoreExtensionsInstaller coreExtensionsInstaller = parent.get(WebCoreExtensionsInstaller.class);
coreExtensionsInstaller.install(container, hasPlatformLevel4OrNone(), noAdditionalSideFilter());
- ServerExtensionInstaller extensionInstaller = get(ServerExtensionInstaller.class);
+
+ ServerExtensionInstaller extensionInstaller = parent.get(ServerExtensionInstaller.class);
extensionInstaller.installExtensions(container);
super.start();
return this;
}
+
}
IndexAction.class,
// Server WS
- SafeModeHealthCheckerModule.class,
- SafemodeSystemWsModule.class,
+ new SafeModeHealthCheckerModule(),
+ new SafemodeSystemWsModule(),
// Listing WS
- WebServicesWsModule.class,
+ new WebServicesWsModule(),
// WS engine
SafeModeUserSession.class,
ServerMonitoringMetrics.class);
addIfStartupLeader(
DatabaseMigrationImpl.class,
- MigrationEngineModule.class,
+ new MigrationEngineModule(),
AutoDbMigration.class)
.otherwiseAdd(NoopDatabaseMigrationImpl.class);
}
}
private boolean anyPluginChanged() {
- return getOptional(DetectPluginChange.class)
+ return parent.getOptional(DetectPluginChange.class)
.map(DetectPluginChange::anyPluginChanged)
- .orElseThrow(() -> new IllegalStateException("DetectPluginChange not available in Pico yet"));
+ .orElseThrow(() -> new IllegalStateException("DetectPluginChange not available in the container yet"));
}
public final class AddIfStartupLeaderAndPluginsChanged extends AddIf {
@Override
public PlatformLevel start() {
- DoPrivileged.execute(new DoPrivileged.Task(get(ThreadLocalUserSession.class)) {
+ DoPrivileged.execute(new DoPrivileged.Task(parent.get(ThreadLocalUserSession.class)) {
@Override
protected void doPrivileged() {
PlatformLevelStartup.super.start();
@Override
public void init(FilterConfig config) {
- // Filters are already available in picocontainer unless a database migration is required. See
+ // Filters are already available in the container unless a database migration is required. See
// org.sonar.server.startup.RegisterServletFilters.
init(config, PlatformImpl.getInstance().getContainer().getComponentsByType(ServletFilter.class));
}
package org.sonar.server.platform.web;
import java.util.Arrays;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.web.ServletFilter;
+import org.springframework.beans.factory.annotation.Autowired;
/**
* @since 3.5
public class RegisterServletFilters implements Startable {
private final ServletFilter[] filters;
+ @Autowired(required = false)
public RegisterServletFilters(ServletFilter[] filters) {
this.filters = filters;
}
+ @Autowired(required = false)
public RegisterServletFilters() {
this(new ServletFilter[0]);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- RequestIdGenerator requestIdGenerator = platform.getContainer().getComponentByType(RequestIdGenerator.class);
+ var requestIdGenerator = platform.getContainer().getOptionalComponentByType(RequestIdGenerator.class);
- if (requestIdGenerator == null) {
+ if (requestIdGenerator.isEmpty()) {
chain.doFilter(request, response);
} else {
- String requestId = requestIdGenerator.generate();
+ String requestId = requestIdGenerator.get().generate();
try (RequestIdMDCStorage mdcStorage = new RequestIdMDCStorage(requestId)) {
request.setAttribute("ID", requestId);
chain.doFilter(request, response);
DBSessions dbSessions = platform.getContainer().getComponentByType(DBSessions.class);
ThreadLocalSettings settings = platform.getContainer().getComponentByType(ThreadLocalSettings.class);
- UserSessionInitializer userSessionInitializer = platform.getContainer().getComponentByType(UserSessionInitializer.class);
+ UserSessionInitializer userSessionInitializer = platform.getContainer().getOptionalComponentByType(UserSessionInitializer.class).orElse(null);
LOG.trace("{} serves {}", Thread.currentThread(), request.getRequestURI());
dbSessions.enableCaching();
import java.util.Properties;
import org.junit.Test;
-import org.sonar.api.config.PropertyDefinition;
-import org.sonar.api.utils.System2;
import org.sonar.server.platform.Platform;
-import org.sonar.server.platform.WebServer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
public class PlatformLevel1Test {
- private PlatformLevel1 underTest = new PlatformLevel1(mock(Platform.class), new Properties());
+ private final PlatformLevel1 underTest = new PlatformLevel1(mock(Platform.class), new Properties());
@Test
public void no_missing_dependencies_between_components() {
underTest.configureLevel();
- assertThat(underTest.getAll(PropertyDefinition.class)).isNotEmpty();
- assertThat(underTest.getOptional(WebServer.class)).isPresent();
- assertThat(underTest.getOptional(System2.class)).isPresent();
+ assertThat(underTest.getContainer().context().getBeanDefinitionNames()).isNotEmpty();
}
}
*/
package org.sonar.server.platform.platformlevel;
+import java.util.Optional;
import java.util.Properties;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.utils.System2;
-import org.sonar.core.platform.PluginRepository;
-import org.sonar.server.platform.Platform;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.server.platform.WebServer;
import org.sonar.server.platform.db.migration.charset.DatabaseCharsetChecker;
+import org.sonar.server.plugins.ServerPluginRepository;
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import static org.sonar.process.ProcessProperties.Property.PATH_DATA;
import static org.sonar.process.ProcessProperties.Property.PATH_HOME;
import static org.sonar.process.ProcessProperties.Property.PATH_TEMP;
@Test
public void add_all_components_by_default() {
- PlatformLevel1 level1 = new PlatformLevel1(mock(Platform.class), props);
- level1.configure();
-
- PlatformLevel2 underTest = new PlatformLevel2(level1);
+ var parentContainer = mock(SpringComponentContainer.class);
+ var container = mock(SpringComponentContainer.class);
+ var platform = mock(PlatformLevel.class);
+ var webserver = mock(WebServer.class);
+
+ when(parentContainer.createChild()).thenReturn(container);
+ when(platform.getContainer()).thenReturn(parentContainer);
+ when(parentContainer.getOptionalComponentByType(any())).thenReturn(Optional.empty());
+ when(container.getOptionalComponentByType(WebServer.class)).thenReturn(Optional.of(webserver));
+ when(webserver.isStartupLeader()).thenReturn(true);
+
+ PlatformLevel2 underTest = new PlatformLevel2(platform);
underTest.configure();
- // some level1 components
- assertThat(underTest.getOptional(WebServer.class)).isPresent();
- assertThat(underTest.getOptional(System2.class)).isPresent();
-
- // level2 component that does not depend on cluster state
- assertThat(underTest.getOptional(PluginRepository.class)).isPresent();
-
- // level2 component that is injected only on "startup leaders"
- assertThat(underTest.getOptional(DatabaseCharsetChecker.class)).isPresent();
+ verify(container).add(ServerPluginRepository.class);
+ verify(container).add(DatabaseCharsetChecker.class);
+ verify(container, times(23)).add(any());
}
@Test
public void do_not_add_all_components_when_startup_follower() {
- props.setProperty("sonar.cluster.enabled", "true");
- PlatformLevel1 level1 = new PlatformLevel1(mock(Platform.class), props);
- level1.configure();
-
- PlatformLevel2 underTest = new PlatformLevel2(level1);
+ var parentContainer = mock(SpringComponentContainer.class);
+ var container = mock(SpringComponentContainer.class);
+ var platform = mock(PlatformLevel.class);
+ var webserver = mock(WebServer.class);
+
+ when(parentContainer.createChild()).thenReturn(container);
+ when(platform.getContainer()).thenReturn(parentContainer);
+ when(parentContainer.getOptionalComponentByType(any())).thenReturn(Optional.empty());
+ when(container.getOptionalComponentByType(WebServer.class)).thenReturn(Optional.of(webserver));
+ when(webserver.isStartupLeader()).thenReturn(false);
+
+ PlatformLevel2 underTest = new PlatformLevel2(platform);
underTest.configure();
- assertThat(underTest.get(WebServer.class).isStartupLeader()).isFalse();
+ verify(container).add(ServerPluginRepository.class);
+ verify(container, never()).add(DatabaseCharsetChecker.class);
+ verify(container, times(21)).add(any());
+ }
- // level2 component that does not depend on cluster state
- assertThat(underTest.getOptional(PluginRepository.class)).isPresent();
- // level2 component that is injected only on "startup leaders"
- assertThat(underTest.getOptional(DatabaseCharsetChecker.class)).isNotPresent();
- }
}
import java.util.Random;
import java.util.stream.IntStream;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import static org.mockito.Mockito.mock;
import org.sonar.server.platform.WebServer;
import static org.assertj.core.api.Assertions.assertThat;
public class PlatformLevelTest {
- private PlatformLevel underTest = new PlatformLevel("name") {
+ private final PlatformLevel underTest = new PlatformLevel("name") {
@Override
protected void configureLevel() {
}
};
+ @Before
+ public void setUp() {
+ underTest.start();
+ }
+
+ @After
+ public void tearDown() {
+ // clean up for next test
+ underTest.stop();
+ }
+
@Test
public void addIfStartupLeader_throws_ISE_if_container_does_not_have_WebServer_object() {
- assertThatThrownBy(() -> underTest.addIfStartupLeader())
+ assertThatThrownBy(underTest::addIfStartupLeader)
.isInstanceOf(IllegalStateException.class)
- .hasMessageContaining("WebServer not available in Pico yet");
+ .hasMessageContaining("WebServer not available in the container");
}
@Test
public void addIfStartupLeader_always_returns_the_same_instance() {
- underTest.add(Mockito.mock(WebServer.class));
+ underTest.add(mock(WebServer.class));
PlatformLevel.AddIfStartupLeader addIfStartupLeader = underTest.addIfStartupLeader();
IntStream.range(0, 1 + new Random().nextInt(4)).forEach(i -> assertThat(underTest.addIfStartupLeader()).isSameAs(addIfStartupLeader));
@Test
public void addIfCluster_throws_ISE_if_container_does_not_have_WebServer_object() {
- assertThatThrownBy(() -> underTest.addIfCluster())
+ assertThatThrownBy(underTest::addIfCluster)
.isInstanceOf(IllegalStateException.class)
- .hasMessageContaining("WebServer not available in Pico yet");
+ .hasMessageContaining("WebServer not available in the container");
}
@Test
public void addIfCluster_always_returns_the_same_instance() {
- underTest.add(Mockito.mock(WebServer.class));
+ underTest.add(mock(WebServer.class));
PlatformLevel.AddIfCluster addIfCluster = underTest.addIfCluster();
IntStream.range(0, 1 + new Random().nextInt(4)).forEach(i -> assertThat(underTest.addIfCluster()).isSameAs(addIfCluster));
@Test
public void addIfStandalone_throws_ISE_if_container_does_not_have_WebServer_object() {
- assertThatThrownBy(() -> underTest.addIfCluster())
+ assertThatThrownBy(underTest::addIfCluster)
.isInstanceOf(IllegalStateException.class)
- .hasMessageContaining("WebServer not available in Pico yet");
+ .hasMessageContaining("WebServer not available in the container");
}
@Test
public void addIfStandalone_always_returns_the_same_instance() {
- underTest.add(Mockito.mock(WebServer.class));
+ underTest.add(mock(WebServer.class));
PlatformLevel.AddIfCluster addIfCluster = underTest.addIfCluster();
IntStream.range(0, 1 + new Random().nextInt(4)).forEach(i -> assertThat(underTest.addIfCluster()).isSameAs(addIfCluster));
package org.sonar.server.platform.web;
import java.io.IOException;
+import java.util.Optional;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.MDC;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ExtensionContainer;
import org.sonar.server.platform.Platform;
import org.sonar.server.platform.web.requestid.RequestIdGenerator;
import static org.mockito.Mockito.when;
public class RequestIdFilterTest {
- private Platform platform = mock(Platform.class);
- private RequestIdGenerator requestIdGenerator = mock(RequestIdGenerator.class);
- private ServletRequest servletRequest = mock(ServletRequest.class);
- private ServletResponse servletResponse = mock(ServletResponse.class);
- private FilterChain filterChain = mock(FilterChain.class);
- private RequestIdFilter underTest = new RequestIdFilter(platform);
+ private final Platform platform = mock(Platform.class);
+ private final RequestIdGenerator requestIdGenerator = mock(RequestIdGenerator.class);
+ private final ServletRequest servletRequest = mock(ServletRequest.class);
+ private final ServletResponse servletResponse = mock(ServletResponse.class);
+ private final FilterChain filterChain = mock(FilterChain.class);
+ private final RequestIdFilter underTest = new RequestIdFilter(platform);
@Before
public void setUp() {
- ComponentContainer container = new ComponentContainer();
- container.add(requestIdGenerator);
+ ExtensionContainer container = mock(ExtensionContainer.class);
+ when(container.getOptionalComponentByType(RequestIdGenerator.class)).thenReturn(Optional.of(requestIdGenerator));
when(platform.getContainer()).thenReturn(container);
}
@Test
public void filter_does_not_fail_when_there_is_no_RequestIdGenerator_in_container() throws IOException, ServletException {
- Platform platform = mock(Platform.class);
- when(platform.getContainer()).thenReturn(new ComponentContainer());
+ ExtensionContainer container = mock(ExtensionContainer.class);
+ when(container.getOptionalComponentByType(RequestIdGenerator.class)).thenReturn(Optional.empty());
+ when(platform.getContainer()).thenReturn(container);
RequestIdFilter underTest = new RequestIdFilter(platform);
underTest.doFilter(servletRequest, servletResponse, filterChain);
@Test
public void filter_does_not_add_requestId_to_request_passed_on_to_chain_when_there_is_no_RequestIdGenerator_in_container() throws IOException, ServletException {
- Platform platform = mock(Platform.class);
- when(platform.getContainer()).thenReturn(new ComponentContainer());
+ ExtensionContainer container = mock(ExtensionContainer.class);
+ when(container.getOptionalComponentByType(RequestIdGenerator.class)).thenReturn(Optional.empty());
+ when(platform.getContainer()).thenReturn(container);
RequestIdFilter underTest = new RequestIdFilter(platform);
underTest.doFilter(servletRequest, servletResponse, filterChain);
package org.sonar.server.platform.web;
import java.io.IOException;
+import java.util.Optional;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ExtensionContainer;
import org.sonar.db.DBSessions;
import org.sonar.server.authentication.UserSessionInitializer;
import org.sonar.server.platform.Platform;
public class UserSessionFilterTest {
- private UserSessionInitializer userSessionInitializer = mock(UserSessionInitializer.class);
- private ComponentContainer container = new ComponentContainer();
- private Platform platform = mock(Platform.class);
- private HttpServletRequest request = mock(HttpServletRequest.class);
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private FilterChain chain = mock(FilterChain.class);
- private DBSessions dbSessions = mock(DBSessions.class);
- private ThreadLocalSettings settings = mock(ThreadLocalSettings.class);
- private UserSessionFilter underTest = new UserSessionFilter(platform);
+ private final UserSessionInitializer userSessionInitializer = mock(UserSessionInitializer.class);
+ private final ExtensionContainer container = mock(ExtensionContainer.class);
+ private final Platform platform = mock(Platform.class);
+ private final HttpServletRequest request = mock(HttpServletRequest.class);
+ private final HttpServletResponse response = mock(HttpServletResponse.class);
+ private final FilterChain chain = mock(FilterChain.class);
+ private final DBSessions dbSessions = mock(DBSessions.class);
+ private final ThreadLocalSettings settings = mock(ThreadLocalSettings.class);
+ private final UserSessionFilter underTest = new UserSessionFilter(platform);
@Before
public void setUp() {
- container.add(dbSessions, settings);
+ when(container.getComponentByType(DBSessions.class)).thenReturn(dbSessions);
+ when(container.getComponentByType(ThreadLocalSettings.class)).thenReturn(settings);
+ when(container.getOptionalComponentByType(UserSessionInitializer.class)).thenReturn(Optional.empty());
when(platform.getContainer()).thenReturn(container);
}
}
private void mockUserSessionInitializer(boolean value) {
- container.add(userSessionInitializer);
+ when(container.getOptionalComponentByType(UserSessionInitializer.class)).thenReturn(Optional.of(userSessionInitializer));
when(userSessionInitializer.initUserSession(request, response)).thenReturn(value);
}
private RuntimeException mockUserSessionInitializerRemoveUserSessionFailing() {
- container.add(userSessionInitializer);
+ when(container.getOptionalComponentByType(UserSessionInitializer.class)).thenReturn(Optional.of(userSessionInitializer));
RuntimeException thrown = new RuntimeException("Faking UserSessionInitializer.removeUserSession failing");
doThrow(thrown)
.when(userSessionInitializer)
compile 'commons-codec:commons-codec'
compile 'commons-io:commons-io'
compile 'commons-lang:commons-lang'
+ compile 'javax.annotation:javax.annotation-api'
compile 'javax.inject:javax.inject'
compile 'org.codehaus.sonar:sonar-classloader'
- compile 'org.picocontainer:picocontainer'
compile 'org.slf4j:slf4j-api'
compile 'org.sonarsource.update-center:sonar-update-center-common'
compile 'org.springframework:spring-context'
}
}
- private void addDeclaredExtensions(ExtensionContainer container, Predicate<Object> extensionFilter,
- Predicate<Object> additionalSideFilter, CoreExtension coreExtension) {
+ private void addDeclaredExtensions(ExtensionContainer container, Predicate<Object> extensionFilter, Predicate<Object> additionalSideFilter, CoreExtension coreExtension) {
ContextImpl context = new ContextImpl(container, extensionFilter, additionalSideFilter, coreExtension.getName());
coreExtension.load(context);
}
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.io.IOUtils;
-import org.picocontainer.Startable;
+import org.sonar.api.Startable;
import org.sonar.api.utils.SonarException;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.language;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.springframework.context.annotation.Bean;
+
+public class LanguagesProvider {
+ @Bean("Languages")
+ public Languages provide(Optional<List<Language>> languages) {
+ if (languages.isPresent()) {
+ return new Languages(languages.get().toArray(new Language[0]));
+ } else {
+ return new Languages();
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import java.lang.reflect.Constructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.lang.Nullable;
+
+/**
+ * Taken from Spring's GenericApplicationContext.ClassDerivedBeanDefinition.
+ * The goal is to support multiple constructors when adding extensions for plugins when no annotations are present.
+ * Spring will pick the constructor with the highest number of arguments that it can inject.
+ */
+public class ClassDerivedBeanDefinition extends RootBeanDefinition {
+ public ClassDerivedBeanDefinition(Class<?> beanClass) {
+ super(beanClass);
+ }
+
+ public ClassDerivedBeanDefinition(ClassDerivedBeanDefinition original) {
+ super(original);
+ }
+
+ /**
+ * This method gets called from AbstractAutowireCapableBeanFactory#createBeanInstance when a bean is instantiated.
+ * It first tries to look at annotations or any other methods provided by bean post processors. If a constructor can't be determined, it will fallback to this method.
+ */
+ @Override
+ @Nullable
+ public Constructor<?>[] getPreferredConstructors() {
+ Class<?> clazz = getBeanClass();
+ Constructor<?> primaryCtor = BeanUtils.findPrimaryConstructor(clazz);
+ if (primaryCtor != null) {
+ return new Constructor<?>[] {primaryCtor};
+ }
+ Constructor<?>[] publicCtors = clazz.getConstructors();
+ if (publicCtors.length > 0) {
+ return publicCtors;
+ }
+ return null;
+ }
+
+ @Override
+ public RootBeanDefinition cloneBeanDefinition() {
+ return new ClassDerivedBeanDefinition(this);
+ }
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.core.platform;
-
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import java.lang.annotation.Annotation;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import javax.annotation.Nullable;
-import org.picocontainer.Characteristics;
-import org.picocontainer.ComponentAdapter;
-import org.picocontainer.ComponentFactory;
-import org.picocontainer.ComponentMonitor;
-import org.picocontainer.DefaultPicoContainer;
-import org.picocontainer.LifecycleStrategy;
-import org.picocontainer.MutablePicoContainer;
-import org.picocontainer.PicoContainer;
-import org.picocontainer.behaviors.OptInCaching;
-import org.picocontainer.monitors.NullComponentMonitor;
-import org.sonar.api.ce.ComputeEngineSide;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.scanner.ScannerSide;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.System2;
-
-import static com.google.common.collect.ImmutableList.copyOf;
-import static java.util.Objects.requireNonNull;
-import static java.util.Optional.ofNullable;
-
-@ScannerSide
-@ServerSide
-@ComputeEngineSide
-public class ComponentContainer implements ExtensionContainer {
- public static final int COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER = 2;
-
- private static final class ExtendedDefaultPicoContainer extends DefaultPicoContainer {
- private ExtendedDefaultPicoContainer(ComponentFactory componentFactory, LifecycleStrategy lifecycleStrategy,
- @Nullable PicoContainer parent, ComponentMonitor componentMonitor) {
- super(componentFactory, lifecycleStrategy, parent, componentMonitor);
- }
-
- @Override
- public Object getComponent(final Object componentKeyOrType, final Class<? extends Annotation> annotation) {
- try {
- return super.getComponent(componentKeyOrType, annotation);
- } catch (Throwable t) {
- throw new IllegalStateException("Unable to load component " + componentKeyOrType, t);
- }
- }
-
- @Override
- public MutablePicoContainer makeChildContainer() {
- DefaultPicoContainer pc = new ExtendedDefaultPicoContainer(componentFactory, lifecycleStrategy, this, componentMonitor);
- addChildContainer(pc);
- return pc;
- }
- }
-
- private ComponentContainer parent;
- private final List<ComponentContainer> children = new ArrayList<>();
- private MutablePicoContainer pico;
- private PropertyDefinitions propertyDefinitions;
- private ComponentKeys componentKeys;
-
- /**
- * Create root container
- */
- public ComponentContainer() {
- this(createPicoContainer());
- }
-
- protected ComponentContainer(MutablePicoContainer picoContainer) {
- this(picoContainer, new PropertyDefinitions(System2.INSTANCE));
- }
-
- protected ComponentContainer(MutablePicoContainer picoContainer, PropertyDefinitions propertyDefinitions) {
- requireNonNull(propertyDefinitions, "PropertyDefinitions can not be null");
- this.parent = null;
- this.pico = picoContainer;
- this.componentKeys = new ComponentKeys();
- this.propertyDefinitions = propertyDefinitions;
- addSingleton(propertyDefinitions);
- addSingleton(this);
- }
-
- /**
- * Create child container
- */
- protected ComponentContainer(ComponentContainer parent) {
- this.parent = parent;
- this.pico = parent.pico.makeChildContainer();
- this.parent.children.add(this);
- this.propertyDefinitions = parent.propertyDefinitions;
- this.componentKeys = new ComponentKeys();
- addSingleton(this);
- }
-
- protected void setParent(ComponentContainer parent) {
- this.parent = parent;
- }
-
- public void execute() {
- try {
- startComponents();
- } finally {
- stopComponents();
- }
- }
-
- /**
- * This method MUST NOT be renamed start() because the container is registered itself in picocontainer. Starting
- * a component twice is not authorized.
- */
- public ComponentContainer startComponents() {
- try {
- doBeforeStart();
- pico.start();
- doAfterStart();
- return this;
- } catch (Exception e) {
- throw PicoUtils.propagate(e);
- }
- }
-
- /**
- * This method aims to be overridden
- */
- protected void doBeforeStart() {
- // nothing
- }
-
- /**
- * This method aims to be overridden
- */
- protected void doAfterStart() {
- // nothing
- }
-
- /**
- * This method MUST NOT be renamed stop() because the container is registered itself in picocontainer. Starting
- * a component twice is not authorized.
- */
- public ComponentContainer stopComponents() {
- try {
- stopChildren();
- if (pico.getLifecycleState().isStarted()) {
- pico.stop();
- }
- pico.dispose();
- } finally {
- if (parent != null) {
- parent.removeChild(this);
- }
- }
- return this;
- }
-
- private void stopChildren() {
- // loop over a copy of list of children in reverse order, both to stop last added child first and because children
- // remove themselves from the list of children of their parent (ie. changing this.children)
- Lists.reverse(new ArrayList<>(this.children))
- .forEach(ComponentContainer::stopComponents);
- }
-
- /**
- * @since 3.5
- */
- @Override
- public ComponentContainer add(Object... objects) {
- for (Object object : objects) {
- if (object instanceof ComponentAdapter) {
- addPicoAdapter((ComponentAdapter) object);
- } else if (object instanceof Iterable) {
- add(Iterables.toArray((Iterable) object, Object.class));
- } else {
- addSingleton(object);
- }
- }
- return this;
- }
-
- public void addIfMissing(Object object, Class<?> objectType) {
- if (getComponentByType(objectType) == null) {
- add(object);
- }
- }
-
- @Override
- public ComponentContainer addSingletons(Iterable<?> components) {
- for (Object component : components) {
- addSingleton(component);
- }
- return this;
- }
-
- public ComponentContainer addSingleton(Object component) {
- return addComponent(component, true);
- }
-
- /**
- * @param singleton return always the same instance if true, else a new instance
- * is returned each time the component is requested
- */
- public ComponentContainer addComponent(Object component, boolean singleton) {
- Object key = componentKeys.of(component);
- if (component instanceof ComponentAdapter) {
- pico.addAdapter((ComponentAdapter) component);
- } else {
- try {
- pico.as(singleton ? Characteristics.CACHE : Characteristics.NO_CACHE).addComponent(key, component);
- } catch (Throwable t) {
- throw new IllegalStateException("Unable to register component " + getName(component), t);
- }
- declareExtension("", component);
- }
- return this;
- }
-
- @Override
- public ComponentContainer addExtension(@Nullable PluginInfo pluginInfo, Object extension) {
- Object key = componentKeys.of(extension);
- try {
- pico.as(Characteristics.CACHE).addComponent(key, extension);
- } catch (Throwable t) {
- throw new IllegalStateException("Unable to register extension " + getName(extension) + (pluginInfo != null ? (" from plugin '" + pluginInfo.getKey() + "'") : ""), t);
- }
- declareExtension(pluginInfo, extension);
- return this;
- }
-
- @Override
- public ComponentContainer addExtension(@Nullable String defaultCategory, Object extension) {
- Object key = componentKeys.of(extension);
- try {
- pico.as(Characteristics.CACHE).addComponent(key, extension);
- } catch (Throwable t) {
- throw new IllegalStateException("Unable to register extension " + getName(extension), t);
- }
- declareExtension(defaultCategory, extension);
- return this;
- }
-
- private static String getName(Object extension) {
- if (extension instanceof Class) {
- return ((Class<?>) extension).getName();
- }
- return getName(extension.getClass());
- }
-
- @Override
- public ComponentContainer declareExtension(@Nullable PluginInfo pluginInfo, Object extension) {
- declareExtension(pluginInfo != null ? pluginInfo.getName() : "", extension);
- return this;
- }
-
- @Override
- public ComponentContainer declareExtension(@Nullable String defaultCategory, Object extension) {
- propertyDefinitions.addComponent(extension, ofNullable(defaultCategory).orElse(""));
- return this;
- }
-
- public ComponentContainer addPicoAdapter(ComponentAdapter<?> adapter) {
- pico.addAdapter(adapter);
- return this;
- }
-
- @Override
- public <T> T getComponentByType(Class<T> type) {
- return pico.getComponent(type);
- }
-
- public Object getComponentByKey(Object key) {
- return pico.getComponent(key);
- }
-
- @Override
- public <T> List<T> getComponentsByType(Class<T> tClass) {
- return pico.getComponents(tClass);
- }
-
- public ComponentContainer removeChild(ComponentContainer childToBeRemoved) {
- requireNonNull(childToBeRemoved);
- Iterator<ComponentContainer> childrenIterator = children.iterator();
- while (childrenIterator.hasNext()) {
- ComponentContainer child = childrenIterator.next();
- if (child == childToBeRemoved) {
- if (pico.removeChildContainer(child.pico)) {
- childrenIterator.remove();
- }
- break;
- }
- }
- return this;
- }
-
- public ComponentContainer createChild() {
- return new ComponentContainer(this);
- }
-
- public static MutablePicoContainer createPicoContainer() {
- return new ExtendedDefaultPicoContainer(new OptInCaching(), new StartableCloseableSafeLifecyleStrategy(), null, new NullComponentMonitor());
- }
-
- public ComponentContainer getParent() {
- return parent;
- }
-
- public List<ComponentContainer> getChildren() {
- return copyOf(children);
- }
-
- public MutablePicoContainer getPicoContainer() {
- return pico;
- }
-
- public int size() {
- return pico.getComponentAdapters().size();
- }
-
-}
package org.sonar.core.platform;
import java.util.List;
+import java.util.Optional;
public interface Container {
Container add(Object... objects);
- Container addSingletons(Iterable<?> components);
-
<T> T getComponentByType(Class<T> type);
+ <T> Optional<T> getOptionalComponentByType(Class<T> type);
+
<T> List<T> getComponentsByType(Class<T> type);
Container getParent();
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import javax.annotation.Nullable;
+import org.springframework.beans.factory.config.BeanDefinition;
+
+public class LazyStrategy extends SpringInitStrategy {
+ @Override
+ protected boolean isLazyInit(BeanDefinition beanDefinition, @Nullable Class<?> clazz) {
+ return true;
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import org.sonar.api.Startable;
+import org.springframework.beans.factory.config.BeanDefinition;
+
+import javax.annotation.Nullable;
+
+public class LazyUnlessStartableStrategy extends SpringInitStrategy {
+ @Override
+ protected boolean isLazyInit(BeanDefinition beanDefinition, @Nullable Class<?> clazz) {
+ return clazz == null || !Startable.class.isAssignableFrom(clazz);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import com.google.common.collect.Iterables;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import javax.annotation.Nullable;
+
+import static java.util.Collections.unmodifiableList;
+
+/**
+ * Intended to be used in tests
+ */
+public class ListContainer implements ExtensionContainer {
+ private final List<Object> objects = new ArrayList<>();
+
+ @Override
+ public Container add(Object... objects) {
+ for (Object o : objects) {
+ if (o instanceof Module) {
+ ((Module) o).configure(this);
+ } else if (o instanceof Iterable) {
+ add(Iterables.toArray((Iterable<?>) o, Object.class));
+ } else {
+ this.objects.add(o);
+ }
+ }
+ return this;
+ }
+
+ public List<Object> getAddedObjects() {
+ return unmodifiableList(new ArrayList<>(objects));
+ }
+
+ @Override
+ public <T> T getComponentByType(Class<T> type) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T> Optional<T> getOptionalComponentByType(Class<T> type) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T> List<T> getComponentsByType(Class<T> type) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ExtensionContainer addExtension(@Nullable PluginInfo pluginInfo, Object extension) {
+ add(extension);
+ return this;
+ }
+
+ @Override
+ public ExtensionContainer addExtension(@Nullable String defaultCategory, Object extension) {
+ add(extension);
+ return this;
+ }
+
+ @Override
+ public ExtensionContainer declareExtension(@Nullable PluginInfo pluginInfo, Object extension) {
+ return this;
+ }
+
+ @Override
+ public ExtensionContainer declareExtension(@Nullable String defaultCategory, Object extension) {
+ return this;
+ }
+
+ @Override
+ public ExtensionContainer getParent() {
+ throw new UnsupportedOperationException();
+ }
+}
import static com.google.common.base.Preconditions.checkNotNull;
public abstract class Module {
- private ComponentContainer container;
+ private Container container;
- public Module configure(ComponentContainer container) {
+ public Module configure(Container container) {
this.container = checkNotNull(container);
-
configureModule();
-
return this;
}
for (Object object : objects) {
if (object != null) {
- container.addComponent(object, true);
+ container.add(object);
}
}
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.core.platform;
-
-import com.google.common.base.Throwables;
-import org.picocontainer.PicoLifecycleException;
-
-class PicoUtils {
-
- private PicoUtils() {
- // only static methods
- }
-
- static Throwable sanitize(Throwable t) {
- Throwable result = t;
- Throwable cause = t.getCause();
- if (t instanceof PicoLifecycleException && cause != null) {
- if ("wrapper".equals(cause.getMessage()) && cause.getCause() != null) {
- result = cause.getCause();
- } else {
- result = cause;
- }
- }
- return result;
- }
-
- static RuntimeException propagate(Throwable t) {
- throw Throwables.propagate(sanitize(t));
- }
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+
+public class PriorityBeanFactory extends DefaultListableBeanFactory {
+ /**
+ * Determines highest priority of the bean candidates.
+ * Does not take into account the @Primary annotations.
+ * This gets called from {@link DefaultListableBeanFactory#determineAutowireCandidate} when the bean factory is finding the beans to autowire. That method
+ * checks for @Primary before calling this method.
+ *
+ * The strategy is to look at the @Priority annotations. If there are ties, we give priority to components that were added to child containers over their parents.
+ * If there are still ties, null is returned, which will ultimately cause Spring to throw a NoUniqueBeanDefinitionException.
+ */
+ @Override
+ @Nullable
+ protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
+ List<Bean> candidateBeans = candidates.entrySet().stream()
+ .filter(e -> e.getValue() != null)
+ .map(e -> new Bean(e.getKey(), e.getValue()))
+ .collect(Collectors.toList());
+
+ List<Bean> beansAfterPriority = highestPriority(candidateBeans, b -> getPriority(b.getInstance()));
+ if (beansAfterPriority.isEmpty()) {
+ return null;
+ } else if (beansAfterPriority.size() == 1) {
+ return beansAfterPriority.get(0).getName();
+ }
+
+ List<Bean> beansAfterHierarchy = highestPriority(beansAfterPriority, b -> getHierarchyPriority(b.getName()));
+ if (beansAfterHierarchy.size() == 1) {
+ return beansAfterHierarchy.get(0).getName();
+ }
+
+ return null;
+ }
+
+ private static List<Bean> highestPriority(List<Bean> candidates, PriorityFunction function) {
+ List<Bean> highestPriorityBeans = new ArrayList<>();
+ Integer highestPriority = null;
+
+ for (Bean candidate : candidates) {
+ Integer candidatePriority = function.classify(candidate);
+ if (candidatePriority == null) {
+ candidatePriority = Integer.MAX_VALUE;
+ }
+ if (highestPriority == null) {
+ highestPriority = candidatePriority;
+ highestPriorityBeans.add(candidate);
+ } else if (candidatePriority < highestPriority) {
+ highestPriorityBeans.clear();
+ highestPriority = candidatePriority;
+ highestPriorityBeans.add(candidate);
+ } else if (candidatePriority.equals(highestPriority)) {
+ highestPriorityBeans.add(candidate);
+ }
+ }
+ return highestPriorityBeans;
+ }
+
+ @CheckForNull
+ private Integer getHierarchyPriority(String beanName) {
+ DefaultListableBeanFactory factory = this;
+ int i = 1;
+ while (factory != null) {
+ if (factory.containsBeanDefinition(beanName)) {
+ return i;
+ }
+ factory = (DefaultListableBeanFactory) factory.getParentBeanFactory();
+ i++;
+ }
+ return null;
+ }
+
+ /**
+ * A common mistake when migrating from Pico Container to Spring is to forget to add @Inject or @Autowire annotations to classes that have multiple constructors.
+ * Spring will fail if there is no default no-arg constructor, but it will silently use the no-arg constructor if there is one, never calling the other constructors.
+ * We override this method to fail fast if a class has multiple constructors.
+ */
+ @Override
+ protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
+ if (mbd.hasBeanClass() && mbd.getBeanClass().getConstructors().length > 1) {
+ throw new IllegalStateException("Constructor annotations missing in: " + mbd.getBeanClass());
+ }
+ return super.instantiateBean(beanName, mbd);
+ }
+
+ private static class Bean {
+ private final String name;
+ private final Object instance;
+
+ public Bean(String name, Object instance) {
+ this.name = name;
+ this.instance = instance;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Object getInstance() {
+ return instance;
+ }
+ }
+
+ @FunctionalInterface
+ private interface PriorityFunction {
+ @CheckForNull
+ Integer classify(Bean candidate);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Supplier;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.utils.System2;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static java.util.Collections.emptyList;
+import static java.util.Optional.ofNullable;
+
+public class SpringComponentContainer implements StartableContainer {
+ protected final AnnotationConfigApplicationContext context;
+ @Nullable
+ protected final SpringComponentContainer parent;
+ protected final List<SpringComponentContainer> children = new ArrayList<>();
+
+ private final PropertyDefinitions propertyDefinitions;
+ private final ComponentKeys componentKeys = new ComponentKeys();
+
+ public SpringComponentContainer() {
+ this(null, new PropertyDefinitions(System2.INSTANCE), emptyList(), new LazyUnlessStartableStrategy());
+ }
+
+ protected SpringComponentContainer(List<?> externalExtensions) {
+ this(null, new PropertyDefinitions(System2.INSTANCE), externalExtensions, new LazyUnlessStartableStrategy());
+ }
+
+ protected SpringComponentContainer(SpringComponentContainer parent) {
+ this(parent, parent.propertyDefinitions, emptyList(), new LazyUnlessStartableStrategy());
+ }
+
+ protected SpringComponentContainer(SpringComponentContainer parent, SpringInitStrategy initStrategy) {
+ this(parent, parent.propertyDefinitions, emptyList(), initStrategy);
+ }
+
+ protected SpringComponentContainer(@Nullable SpringComponentContainer parent, PropertyDefinitions propertyDefs, List<?> externalExtensions, SpringInitStrategy initStrategy) {
+ this.parent = parent;
+ this.propertyDefinitions = propertyDefs;
+ this.context = new AnnotationConfigApplicationContext(new PriorityBeanFactory());
+ this.context.setAllowBeanDefinitionOverriding(false);
+ ((AbstractAutowireCapableBeanFactory) context.getBeanFactory()).setParameterNameDiscoverer(null);
+ if (parent != null) {
+ context.setParent(parent.context);
+ parent.children.add(this);
+ }
+ add(initStrategy);
+ add(this);
+ add(new StartableBeanPostProcessor());
+ add(externalExtensions);
+ add(propertyDefs);
+ }
+
+ /**
+ * Beans need to have a unique name, otherwise they'll override each other.
+ * The strategy is:
+ * - For classes, use the classloader + fully qualified class name as the name of the bean
+ * - For instances, use the Classloader + FQCN + toString()
+ * - If the object is a collection, iterate through the elements and apply the same strategy for each of them
+ */
+ @Override
+ public Container add(Object... objects) {
+ for (Object o : objects) {
+ if (o instanceof Class) {
+ Class<?> clazz = (Class<?>) o;
+ if (Module.class.isAssignableFrom(clazz)) {
+ throw new IllegalStateException("Modules should be added as instances");
+ }
+ context.registerBean(componentKeys.ofClass(clazz), clazz);
+ declareExtension("", o);
+ } else if (o instanceof Module) {
+ ((Module) o).configure(this);
+ } else if (o instanceof Iterable) {
+ add(Iterables.toArray((Iterable<?>) o, Object.class));
+ } else {
+ registerInstance(o);
+ declareExtension("", o);
+ }
+ }
+ return this;
+ }
+
+ private <T> void registerInstance(T instance) {
+ Supplier<T> supplier = () -> instance;
+ Class<T> clazz = (Class<T>) instance.getClass();
+ context.registerBean(componentKeys.ofInstance(instance), clazz, supplier);
+ }
+
+ /**
+ * Extensions are usually added by plugins and we assume they don't support any injection-related annotations.
+ * Spring contexts supporting annotations will fail if multiple constructors are present without any annotations indicating which one to use for injection.
+ * For that reason, we need to create the beans ourselves, using ClassDerivedBeanDefinition, which will declare that all constructors can be used for injection.
+ */
+ private Container addExtension(Object o) {
+ if (o instanceof Class) {
+ Class<?> clazz = (Class<?>) o;
+ ClassDerivedBeanDefinition bd = new ClassDerivedBeanDefinition(clazz);
+ context.registerBeanDefinition(componentKeys.ofClass(clazz), bd);
+ } else if (o instanceof Iterable) {
+ ((Iterable<?>) o).forEach(this::addExtension);
+ } else {
+ registerInstance(o);
+ }
+ return this;
+ }
+
+ @Override
+ public <T> T getComponentByType(Class<T> type) {
+ try {
+ return context.getBean(type);
+ } catch (Exception t) {
+ throw new IllegalStateException("Unable to load component " + type, t);
+ }
+ }
+
+ @Override public <T> Optional<T> getOptionalComponentByType(Class<T> type) {
+ try {
+ return Optional.of(context.getBean(type));
+ } catch (NoSuchBeanDefinitionException t) {
+ return Optional.empty();
+ }
+ }
+
+ @Override
+ public <T> List<T> getComponentsByType(Class<T> type) {
+ try {
+ return new ArrayList<>(context.getBeansOfType(type).values());
+ } catch (Exception t) {
+ throw new IllegalStateException("Unable to load components " + type, t);
+ }
+ }
+
+ public AnnotationConfigApplicationContext context() {
+ return context;
+ }
+
+ public void execute() {
+ RuntimeException r = null;
+ try {
+ startComponents();
+ } catch (RuntimeException e) {
+ r = e;
+ } finally {
+ try {
+ stopComponents();
+ } catch (RuntimeException e) {
+ if (r == null) {
+ r = e;
+ }
+ }
+ }
+ if (r != null) {
+ throw r;
+ }
+ }
+
+ @Override
+ public SpringComponentContainer startComponents() {
+ doBeforeStart();
+ context.refresh();
+ doAfterStart();
+ return this;
+ }
+
+ public SpringComponentContainer stopComponents() {
+ try {
+ stopChildren();
+ if (context.isActive()) {
+ context.close();
+ }
+ } finally {
+ if (parent != null) {
+ parent.children.remove(this);
+ }
+ }
+ return this;
+ }
+
+ private void stopChildren() {
+ // loop over a copy of list of children in reverse order
+ Lists.reverse(new ArrayList<>(this.children)).forEach(SpringComponentContainer::stopComponents);
+ }
+
+ public SpringComponentContainer createChild() {
+ return new SpringComponentContainer(this);
+ }
+
+ @Override
+ @CheckForNull
+ public SpringComponentContainer getParent() {
+ return parent;
+ }
+
+ @Override
+ public SpringComponentContainer addExtension(@Nullable PluginInfo pluginInfo, Object extension) {
+ addExtension(extension);
+ declareExtension(pluginInfo, extension);
+ return this;
+ }
+
+ @Override
+ public SpringComponentContainer addExtension(@Nullable String defaultCategory, Object extension) {
+ addExtension(extension);
+ declareExtension(defaultCategory, extension);
+ return this;
+ }
+
+ @Override
+ public SpringComponentContainer declareExtension(@Nullable PluginInfo pluginInfo, Object extension) {
+ declareExtension(pluginInfo != null ? pluginInfo.getName() : "", extension);
+ return this;
+ }
+
+ @Override
+ public SpringComponentContainer declareExtension(@Nullable String defaultCategory, Object extension) {
+ this.propertyDefinitions.addComponent(extension, ofNullable(defaultCategory).orElse(""));
+ return this;
+ }
+
+ /**
+ * This method aims to be overridden
+ */
+ protected void doBeforeStart() {
+ // nothing
+ }
+
+ /**
+ * This method aims to be overridden
+ */
+ protected void doAfterStart() {
+ // nothing
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import javax.annotation.Nullable;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+
+public abstract class SpringInitStrategy implements BeanFactoryPostProcessor {
+ @Override
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ for (String beanName : beanFactory.getBeanDefinitionNames()) {
+ BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
+ Class<?> rawClass = beanDefinition.getResolvableType().getRawClass();
+ beanDefinition.setLazyInit(isLazyInit(beanDefinition, rawClass));
+ }
+ }
+
+ protected abstract boolean isLazyInit(BeanDefinition beanDefinition, @Nullable Class<?> clazz);
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import org.sonar.api.Startable;
+import org.sonar.api.utils.log.Loggers;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
+import org.springframework.lang.Nullable;
+
+public class StartableBeanPostProcessor implements DestructionAwareBeanPostProcessor {
+ @Override
+ @Nullable
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ if (bean instanceof Startable) {
+ ((Startable) bean).start();
+ }
+ return bean;
+ }
+
+ @Override
+ public boolean requiresDestruction(Object bean) {
+ return bean instanceof Startable;
+ }
+
+ @Override
+ public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
+ try {
+ // note: Spring will call close() on AutoCloseable beans.
+ if (bean instanceof Startable) {
+ ((Startable) bean).stop();
+ }
+ } catch (Exception e) {
+ Loggers.get(StartableBeanPostProcessor.class)
+ .warn("Dispose of component {} failed", bean.getClass().getCanonicalName(), e);
+ }
+ }
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.core.platform;
-
-import java.io.Closeable;
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.stream.Stream;
-import org.picocontainer.ComponentAdapter;
-import org.picocontainer.LifecycleStrategy;
-import org.picocontainer.Startable;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-public class StartableCloseableSafeLifecyleStrategy implements LifecycleStrategy, Serializable {
- private static final Class<?>[] TYPES_WITH_LIFECYCLE = new Class[] {Startable.class, org.sonar.api.Startable.class, Closeable.class, AutoCloseable.class};
-
- private static final Logger LOG = Loggers.get(StartableCloseableSafeLifecyleStrategy.class);
-
- @Override
- public void start(Object component) {
- if (component instanceof Startable) {
- ((Startable) component).start();
- } else if (component instanceof org.sonar.api.Startable) {
- ((org.sonar.api.Startable) component).start();
- }
- }
-
- @Override
- public void stop(Object component) {
- try {
- if (component instanceof Startable) {
- ((Startable) component).stop();
- } else if (component instanceof org.sonar.api.Startable) {
- ((org.sonar.api.Startable) component).stop();
- }
- } catch (RuntimeException | Error e) {
- Loggers.get(StartableCloseableSafeLifecyleStrategy.class)
- .warn("Stopping of component {} failed", component.getClass().getCanonicalName(), e);
- }
- }
-
- @Override
- public void dispose(Object component) {
- try {
- if (component instanceof Closeable) {
- ((Closeable) component).close();
- } else if (component instanceof AutoCloseable) {
- ((AutoCloseable) component).close();
- }
- } catch (Exception e) {
- Loggers.get(StartableCloseableSafeLifecyleStrategy.class)
- .warn("Dispose of component {} failed", component.getClass().getCanonicalName(), e);
- }
- }
-
- @Override
- public boolean hasLifecycle(Class<?> type) {
- if (Arrays.stream(TYPES_WITH_LIFECYCLE).anyMatch(t1 -> t1.isAssignableFrom(type))) {
- return true;
- }
-
- if (Stream.of("start", "stop").anyMatch(t -> hasMethod(type, t))) {
- LOG.warn("Component of type {} defines methods start() and/or stop(). Neither will be invoked to start/stop the component." +
- " Please implement either {} or {}",
- type, Startable.class.getName(), org.sonar.api.Startable.class.getName());
- }
- if (hasMethod(type, "close")) {
- LOG.warn("Component of type {} defines method close(). It won't be invoked to dispose the component." +
- " Please implement either {} or {}",
- type, Closeable.class.getName(), AutoCloseable.class.getName());
- }
- return false;
- }
-
- private static boolean hasMethod(Class<?> type, String methodName) {
- try {
- return type.getMethod(methodName) != null;
- } catch (NoSuchMethodException e) {
- return false;
- }
- }
-
- @Override
- public boolean isLazy(ComponentAdapter<?> adapter) {
- return false;
- }
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+public interface StartableContainer extends ExtensionContainer {
+ StartableContainer startComponents();
+}
/**
* Should be removed as long {@link Uuids} is not used anymore. {@code UuidFactoryImpl}
- * should be built by picocontainer through a public constructor.
+ * should be injected by the ioc container through a public constructor.
*/
INSTANCE;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mockito;
-import org.picocontainer.ComponentAdapter;
import org.sonar.api.Property;
import org.sonar.api.SonarRuntime;
import org.sonar.api.config.Configuration;
import org.sonar.api.config.PropertyDefinition;
-import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.internal.MapSettings;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ExtensionContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
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.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
@RunWith(DataProviderRunner.class)
public class CoreExtensionsInstallerTest {
- private SonarRuntime sonarRuntime = mock(SonarRuntime.class);
- private CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class);
- private CoreExtensionsInstaller underTest = new CoreExtensionsInstaller(sonarRuntime, coreExtensionRepository, WestSide.class) {
+ private final SonarRuntime sonarRuntime = mock(SonarRuntime.class);
+ private final CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class);
+ private final CoreExtensionsInstaller underTest = new CoreExtensionsInstaller(sonarRuntime, coreExtensionRepository, WestSide.class) {
};
- private ArgumentCaptor<CoreExtension.Context> contextCaptor = ArgumentCaptor.forClass(CoreExtension.Context.class);
+ private final ArgumentCaptor<CoreExtension.Context> contextCaptor = ArgumentCaptor.forClass(CoreExtension.Context.class);
private static int name_counter = 0;
@Test
public void install_has_no_effect_if_CoreExtensionRepository_has_no_loaded_CoreExtension() {
- ComponentContainer container = new ComponentContainer();
-
+ ListContainer container = new ListContainer();
underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
-
assertAddedExtensions(container, 0);
}
List<CoreExtension> coreExtensions = ImmutableList.of(coreExtension1, coreExtension2, coreExtension3, coreExtension4);
InOrder inOrder = Mockito.inOrder(coreExtension1, coreExtension2, coreExtension3, coreExtension4);
when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(coreExtensions.stream());
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
CoreExtension coreExtension1 = newCoreExtension();
CoreExtension coreExtension2 = newCoreExtension();
when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension1, coreExtension2));
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
CoreExtension coreExtension1 = newCoreExtension();
CoreExtension coreExtension2 = newCoreExtension();
when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension1, coreExtension2));
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
CoreExtension coreExtension2 = newCoreExtension();
when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension1, coreExtension2));
Configuration configuration = new MapSettings().asConfig();
- ComponentContainer container = new ComponentContainer();
- container.add(configuration);
-
+ ExtensionContainer container = mock(ExtensionContainer.class);
+ when(container.getComponentByType(Configuration.class)).thenReturn(configuration);
underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
verify(coreExtension1).load(contextCaptor.capture());
List<Object> extensions = ImmutableList.of(WestSideClass.class, EastSideClass.class, OtherSideClass.class, Latitude.class);
CoreExtension coreExtension = newCoreExtension(context -> extensionAdder.accept(context, extensions));
when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
- ComponentContainer container = new ComponentContainer();
+ ExtensionContainer container = mock(ExtensionContainer.class);
underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
- assertAddedExtensions(container, WestSideClass.class, Latitude.class);
- assertPropertyDefinitions(container);
+ verify(container).addExtension(coreExtension.getName(), WestSideClass.class);
+ verify(container).declareExtension(coreExtension.getName(), OtherSideClass.class);
+ verify(container).declareExtension(coreExtension.getName(), EastSideClass.class);
+ verify(container).addExtension(coreExtension.getName(), Latitude.class);
+ verifyNoMoreInteractions(container);
}
@Test
List<Object> extensions = ImmutableList.of(WestSideClass.class, EastSideClass.class, OtherSideClass.class, Latitude.class);
CoreExtension coreExtension = newCoreExtension(context -> extensionAdder.accept(context, extensions));
when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
- ComponentContainer container = new ComponentContainer();
+ ExtensionContainer container = mock(ExtensionContainer.class);
underTest.install(container, noExtensionFilter(), t -> t != Latitude.class);
- assertAddedExtensions(container, WestSideClass.class);
- assertPropertyDefinitions(container);
- }
-
- @Test
- @UseDataProvider("allMethodsToAddExtension")
- public void install_adds_PropertyDefinition_from_annotation_no_matter_annotations(BiConsumer<CoreExtension.Context, Collection<Object>> extensionAdder) {
- List<Object> extensions = ImmutableList.of(WestSidePropertyDefinition.class, EastSidePropertyDefinition.class,
- OtherSidePropertyDefinition.class, LatitudePropertyDefinition.class, BlankPropertyDefinition.class);
- CoreExtension coreExtension = newCoreExtension(context -> extensionAdder.accept(context, extensions));
- when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
- ComponentContainer container = new ComponentContainer();
-
- underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
-
- assertAddedExtensions(container, WestSidePropertyDefinition.class, LatitudePropertyDefinition.class);
- assertPropertyDefinitions(container, "westKey", "eastKey", "otherKey", "latitudeKey", "blankKey");
- }
-
- @Test
- @UseDataProvider("allMethodsToAddExtension")
- public void install_adds_PropertyDefinition_from_annotation_no_matter_annotations_even_if_filtered_out(BiConsumer<CoreExtension.Context, Collection<Object>> extensionAdder) {
- List<Object> extensions = ImmutableList.of(WestSidePropertyDefinition.class, EastSidePropertyDefinition.class,
- OtherSidePropertyDefinition.class, LatitudePropertyDefinition.class, BlankPropertyDefinition.class);
- CoreExtension coreExtension = newCoreExtension(context -> extensionAdder.accept(context, extensions));
- when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
- ComponentContainer container = new ComponentContainer();
-
- underTest.install(container, noExtensionFilter(), t -> false);
-
- assertAddedExtensions(container, 0);
- assertPropertyDefinitions(container, "westKey", "eastKey", "otherKey", "latitudeKey", "blankKey");
+ verify(container).addExtension(coreExtension.getName(), WestSideClass.class);
+ verify(container).declareExtension(coreExtension.getName(), OtherSideClass.class);
+ verify(container).declareExtension(coreExtension.getName(), EastSideClass.class);
+ verify(container).declareExtension(coreExtension.getName(), Latitude.class);
+ verifyNoMoreInteractions(container);
}
@Test
List<Object> extensions = ImmutableList.of(propertyDefinitionNoCategory, propertyDefinitionWithCategory);
CoreExtension coreExtension = newCoreExtension(context -> extensionAdder.accept(context, extensions));
when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
- ComponentContainer container = new ComponentContainer();
+ ExtensionContainer container = mock(ExtensionContainer.class);
underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
- assertAddedExtensions(container, 0);
- assertPropertyDefinitions(container, coreExtension, propertyDefinitionNoCategory, propertyDefinitionWithCategory);
+ verify(container).declareExtension(coreExtension.getName(), propertyDefinitionNoCategory);
+ verify(container).declareExtension(coreExtension.getName(), propertyDefinitionWithCategory);
+ verifyNoMoreInteractions(container);
}
@DataProvider
};
}
- private static void assertAddedExtensions(ComponentContainer container, int addedExtensions) {
- Collection<ComponentAdapter<?>> adapters = container.getPicoContainer().getComponentAdapters();
- assertThat(adapters)
- .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + addedExtensions);
- }
-
- private static void assertAddedExtensions(ComponentContainer container, Class... classes) {
- Collection<ComponentAdapter<?>> adapters = container.getPicoContainer().getComponentAdapters();
+ private static void assertAddedExtensions(ListContainer container, int addedExtensions) {
+ List<Object> adapters = container.getAddedObjects();
assertThat(adapters)
- .hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + classes.length);
-
- Stream<Class> installedExtensions = adapters.stream()
- .map(t -> (Class) t.getComponentImplementation())
- .filter(t -> !PropertyDefinitions.class.isAssignableFrom(t) && t != ComponentContainer.class);
- assertThat(installedExtensions)
- .contains(classes)
- .hasSize(classes.length);
- }
-
- private void assertPropertyDefinitions(ComponentContainer container, String... keys) {
- PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
- if (keys.length == 0) {
- assertThat(propertyDefinitions.getAll()).isEmpty();
- } else {
- for (String key : keys) {
- assertThat(propertyDefinitions.get(key)).isNotNull();
- }
- }
- }
-
- private void assertPropertyDefinitions(ComponentContainer container, CoreExtension coreExtension, PropertyDefinition... definitions) {
- PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
- if (definitions.length == 0) {
- assertThat(propertyDefinitions.getAll()).isEmpty();
- } else {
- for (PropertyDefinition definition : definitions) {
- PropertyDefinition actual = propertyDefinitions.get(definition.key());
- assertThat(actual.category()).isEqualTo(definition.category() == null ? coreExtension.getName() : definition.category());
- }
- }
+ .hasSize(addedExtensions);
}
private static CoreExtension newCoreExtension() {
}
- @Property(key = "westKey", name = "westName")
- @WestSide
- public static class WestSidePropertyDefinition {
-
- }
-
@Property(key = "eastKey", name = "eastName")
@EastSide
public static class EastSidePropertyDefinition {
}
- @Property(key = "latitudeKey", name = "latitudeName")
- @WestSide
- @EastSide
- public static class LatitudePropertyDefinition {
-
- }
-
@Property(key = "blankKey", name = "blankName")
public static class BlankPropertyDefinition {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.language;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+public class LanguagesProviderTest {
+
+ @Test
+ public void should_provide_default_instance_when_no_language() {
+ LanguagesProvider provider = new LanguagesProvider();
+ Languages languages = provider.provide(Optional.empty());
+
+ assertThat(languages).isNotNull();
+ assertThat(languages.all()).isEmpty();
+ }
+
+ @Test
+ public void should_provide_instance_when_languages() {
+ Language A = mock(Language.class);
+ when(A.getKey()).thenReturn("a");
+ Language B = mock(Language.class);
+ when(B.getKey()).thenReturn("b");
+
+ LanguagesProvider provider = new LanguagesProvider();
+ List<Language> languageList = Arrays.asList(A, B);
+ Languages languages = provider.provide(Optional.of(languageList));
+
+ assertThat(languages).isNotNull();
+ assertThat(languages.all())
+ .hasSize(2)
+ .contains(A, B);
+ }
+
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.core.platform;
-
-import java.io.Closeable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import org.junit.Test;
-import org.picocontainer.Startable;
-import org.picocontainer.injectors.ProviderAdapter;
-import org.sonar.api.Property;
-import org.sonar.api.config.PropertyDefinitions;
-
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-public class ComponentContainerTest {
-
-
- @Test
- public void shouldRegisterItself() {
- ComponentContainer container = new ComponentContainer();
- assertThat(container.getComponentByType(ComponentContainer.class)).isSameAs(container);
- }
-
- @Test
- public void should_start_and_stop_component_extending_pico_Startable() {
- ComponentContainer container = spy(new ComponentContainer());
- container.addSingleton(StartableStoppableComponent.class);
- container.startComponents();
-
- assertThat(container.getComponentByType(StartableStoppableComponent.class).started).isTrue();
- assertThat(container.getComponentByType(StartableStoppableComponent.class).stopped).isFalse();
- verify(container).doBeforeStart();
- verify(container).doAfterStart();
-
- container.stopComponents();
- assertThat(container.getComponentByType(StartableStoppableComponent.class).stopped).isTrue();
- }
-
- @Test
- public void should_start_and_stop_component_extending_API_Startable() {
- ComponentContainer container = spy(new ComponentContainer());
- container.addSingleton(StartableStoppableApiComponent.class);
- container.startComponents();
-
- assertThat(container.getComponentByType(StartableStoppableApiComponent.class).started).isTrue();
- assertThat(container.getComponentByType(StartableStoppableApiComponent.class).stopped).isFalse();
- verify(container).doBeforeStart();
- verify(container).doAfterStart();
-
- container.stopComponents();
- assertThat(container.getComponentByType(StartableStoppableApiComponent.class).stopped).isTrue();
- }
-
- @Test
- public void should_not_start_and_stop_component_just_having_start_and_stop_method() {
- ComponentContainer container = spy(new ComponentContainer());
- container.addSingleton(ReflectionStartableStoppableComponent.class);
- container.startComponents();
-
- assertThat(container.getComponentByType(ReflectionStartableStoppableComponent.class).started).isFalse();
- assertThat(container.getComponentByType(ReflectionStartableStoppableComponent.class).stopped).isFalse();
- verify(container).doBeforeStart();
- verify(container).doAfterStart();
-
- container.stopComponents();
- assertThat(container.getComponentByType(ReflectionStartableStoppableComponent.class).started).isFalse();
- assertThat(container.getComponentByType(ReflectionStartableStoppableComponent.class).stopped).isFalse();
- }
-
- @Test
- public void should_start_and_stop_hierarchy_of_containers() {
- StartableStoppableComponent parentComponent = new StartableStoppableComponent();
- final StartableStoppableComponent childComponent = new StartableStoppableComponent();
- ComponentContainer parentContainer = new ComponentContainer() {
- @Override
- public void doAfterStart() {
- ComponentContainer childContainer = new ComponentContainer(this);
- childContainer.add(childComponent);
- childContainer.execute();
- }
- };
- parentContainer.add(parentComponent);
- parentContainer.execute();
- assertThat(parentComponent.started).isTrue();
- assertThat(parentComponent.stopped).isTrue();
- assertThat(childComponent.started).isTrue();
- assertThat(childComponent.stopped).isTrue();
- }
-
- @Test
- public void should_stop_hierarchy_of_containers_on_failure() {
- StartableStoppableComponent parentComponent = new StartableStoppableComponent();
- final StartableStoppableComponent childComponent1 = new StartableStoppableComponent();
- final UnstartableComponent childComponent2 = new UnstartableComponent();
- ComponentContainer parentContainer = new ComponentContainer() {
- @Override
- public void doAfterStart() {
- ComponentContainer childContainer = new ComponentContainer(this);
- childContainer.add(childComponent1);
- childContainer.add(childComponent2);
- childContainer.execute();
- }
- };
- parentContainer.add(parentComponent);
- try {
- parentContainer.execute();
- fail();
- } catch (Exception e) {
- assertThat(parentComponent.started).isTrue();
- assertThat(parentComponent.stopped).isTrue();
- assertThat(childComponent1.started).isTrue();
- assertThat(childComponent1.stopped).isTrue();
- }
- }
-
- @Test
- public void testChild() {
- ComponentContainer parent = new ComponentContainer();
- parent.startComponents();
-
- ComponentContainer child = parent.createChild();
- child.addSingleton(StartableStoppableComponent.class);
- child.startComponents();
-
- assertThat(child.getParent()).isSameAs(parent);
- assertThat(parent.getChildren()).containsOnly(child);
- assertThat(child.getComponentByType(ComponentContainer.class)).isSameAs(child);
- assertThat(parent.getComponentByType(ComponentContainer.class)).isSameAs(parent);
- assertThat(child.getComponentByType(StartableStoppableComponent.class)).isNotNull();
- assertThat(parent.getComponentByType(StartableStoppableComponent.class)).isNull();
-
- parent.stopComponents();
- }
-
- @Test
- public void testRemoveChild() {
- ComponentContainer parent = new ComponentContainer();
- parent.startComponents();
-
- ComponentContainer child = parent.createChild();
- assertThat(parent.getChildren()).containsOnly(child);
-
- parent.removeChild(child);
- assertThat(parent.getChildren()).isEmpty();
- }
-
- @Test
- public void support_multiple_children() {
- ComponentContainer parent = new ComponentContainer();
- parent.startComponents();
- ComponentContainer child1 = parent.createChild();
- child1.startComponents();
- ComponentContainer child2 = parent.createChild();
- child2.startComponents();
- assertThat(parent.getChildren()).containsOnly(child1, child2);
-
- child1.stopComponents();
- assertThat(parent.getChildren()).containsOnly(child2);
-
- parent.stopComponents();
- assertThat(parent.getChildren()).isEmpty();
- }
-
- @Test
- public void shouldForwardStartAndStopToDescendants() {
- ComponentContainer grandParent = new ComponentContainer();
- ComponentContainer parent = grandParent.createChild();
- ComponentContainer child = parent.createChild();
- child.addSingleton(StartableStoppableComponent.class);
-
- grandParent.startComponents();
-
- StartableStoppableComponent component = child.getComponentByType(StartableStoppableComponent.class);
- assertTrue(component.started);
-
- parent.stopComponents();
- assertTrue(component.stopped);
- }
-
- @Test
- public void shouldDeclareComponentProperties() {
- ComponentContainer container = new ComponentContainer();
- container.addSingleton(ComponentWithProperty.class);
-
- PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
- assertThat(propertyDefinitions.get("foo")).isNotNull();
- assertThat(propertyDefinitions.get("foo").defaultValue()).isEqualTo("bar");
- }
-
- @Test
- public void shouldDeclareExtensionWithoutAddingIt() {
- ComponentContainer container = new ComponentContainer();
- PluginInfo plugin = mock(PluginInfo.class);
- container.declareExtension(plugin, ComponentWithProperty.class);
-
- PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
- assertThat(propertyDefinitions.get("foo")).isNotNull();
- assertThat(container.getComponentByType(ComponentWithProperty.class)).isNull();
- }
-
- @Test
- public void shouldDeclareExtensionWhenAdding() {
- ComponentContainer container = new ComponentContainer();
- PluginInfo plugin = mock(PluginInfo.class);
- container.addExtension(plugin, ComponentWithProperty.class);
-
- PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
- assertThat(propertyDefinitions.get("foo")).isNotNull();
- assertThat(container.getComponentByType(ComponentWithProperty.class)).isNotNull();
- assertThat(container.getComponentByKey(ComponentWithProperty.class)).isNotNull();
- }
-
- @Test
- public void test_add_class() {
- ComponentContainer container = new ComponentContainer();
- container.add(ComponentWithProperty.class, SimpleComponent.class);
- assertThat(container.getComponentByType(ComponentWithProperty.class)).isNotNull();
- assertThat(container.getComponentByType(SimpleComponent.class)).isNotNull();
- }
-
- @Test
- public void test_add_collection() {
- ComponentContainer container = new ComponentContainer();
- container.add(Arrays.asList(ComponentWithProperty.class, SimpleComponent.class));
- assertThat(container.getComponentByType(ComponentWithProperty.class)).isNotNull();
- assertThat(container.getComponentByType(SimpleComponent.class)).isNotNull();
- }
-
- @Test
- public void test_add_adapter() {
- ComponentContainer container = new ComponentContainer();
- container.add(new SimpleComponentProvider());
- assertThat(container.getComponentByType(SimpleComponent.class)).isNotNull();
- }
-
- @Test
- public void should_sanitize_pico_exception_on_start_failure() {
- ComponentContainer container = new ComponentContainer();
- container.add(UnstartableComponent.class);
-
- // do not expect a PicoException
- assertThatThrownBy(container::startComponents)
- .isInstanceOf(IllegalStateException.class);
- }
-
- @Test
- public void display_plugin_name_when_failing_to_add_extension() {
- ComponentContainer container = new ComponentContainer();
- PluginInfo plugin = mock(PluginInfo.class);
-
- container.startComponents();
-
- assertThatThrownBy(() -> container.addExtension(plugin, UnstartableComponent.class))
- .isInstanceOf(IllegalStateException.class)
- .hasMessageContaining("Unable to register extension org.sonar.core.platform.ComponentContainerTest$UnstartableComponent");
- }
-
- @Test
- public void test_start_failure() {
- ComponentContainer container = new ComponentContainer();
- StartableStoppableComponent startable = new StartableStoppableComponent();
- container.add(startable, UnstartableComponent.class);
-
- try {
- container.execute();
- fail();
- } catch (Exception e) {
- assertThat(startable.started).isTrue();
-
- // container stops the components that have already been started
- assertThat(startable.stopped).isTrue();
- }
- }
-
- @Test
- public void stop_container_does_not_fail_and_all_stoppable_components_are_stopped_even_if_one_or_more_stop_method_call_fail() {
- ComponentContainer container = new ComponentContainer();
- container.add(FailingStopWithISEComponent.class, FailingStopWithISEComponent2.class, FailingStopWithErrorComponent.class, FailingStopWithErrorComponent2.class);
- container.startComponents();
- StartableStoppableComponent[] components = {
- container.getComponentByType(FailingStopWithISEComponent.class),
- container.getComponentByType(FailingStopWithISEComponent2.class),
- container.getComponentByType(FailingStopWithErrorComponent.class),
- container.getComponentByType(FailingStopWithErrorComponent2.class)
- };
-
- container.stopComponents();
-
- Arrays.stream(components).forEach(startableComponent -> assertThat(startableComponent.stopped).isTrue());
- }
-
- @Test
- public void stop_container_stops_all_stoppable_components_even_in_case_of_OOM_in_any_stop_method() {
- ComponentContainer container = new ComponentContainer();
- container.add(FailingStopWithOOMComponent.class, FailingStopWithOOMComponent2.class);
- container.startComponents();
- StartableStoppableComponent[] components = {
- container.getComponentByType(FailingStopWithOOMComponent.class),
- container.getComponentByType(FailingStopWithOOMComponent2.class)
- };
-
- container.stopComponents();
-
- assertThat(container.getPicoContainer().getLifecycleState().isDisposed()).isTrue();
- Arrays.stream(components).forEach(cpt -> assertThat(cpt.stopped).isTrue());
- }
-
- @Test
- public void stop_exception_should_not_hide_start_exception() {
- ComponentContainer container = new ComponentContainer();
- container.add(UnstartableComponent.class, FailingStopWithISEComponent.class);
-
- assertThatThrownBy(container::execute)
- .isInstanceOf(IllegalStateException.class)
- .hasMessage("Fail to start");
- }
-
- @Test
- public void stop_exceptionin_API_component_should_not_hide_start_exception() {
- ComponentContainer container = new ComponentContainer();
- container.add(UnstartableApiComponent.class, FailingStopWithISEComponent.class);
-
- assertThatThrownBy(container::execute)
- .isInstanceOf(IllegalStateException.class)
- .hasMessage("Fail to start");
- }
-
- @Test
- public void should_execute_components() {
- ComponentContainer container = new ComponentContainer();
- StartableStoppableComponent component = new StartableStoppableComponent();
- container.add(component);
-
- container.execute();
-
- assertThat(component.started).isTrue();
- assertThat(component.stopped).isTrue();
- }
-
- /**
- * Method close() must be called even if the methods start() or stop()
- * are not defined.
- */
- @Test
- public void should_close_components_without_lifecycle() {
- ComponentContainer container = new ComponentContainer();
- CloseableComponent component = new CloseableComponent();
- container.add(component);
-
- container.execute();
-
- assertThat(component.isClosed).isTrue();
- }
-
- /**
- * Method close() must be executed after stop()
- */
- @Test
- public void should_close_Closeable_components_with_lifecycle() {
- ComponentContainer container = new ComponentContainer();
- StartableCloseableComponent component = new StartableCloseableComponent();
- container.add(component);
-
- container.execute();
-
- assertThat(component.isStopped).isTrue();
- assertThat(component.isClosed).isTrue();
- assertThat(component.isClosedAfterStop).isTrue();
- }
-
- /**
- * Method close() must be executed after stop()
- */
- @Test
- public void should_close_AutoCloseable_components_with_lifecycle() {
- ComponentContainer container = new ComponentContainer();
- StartableAutoCloseableComponent component = new StartableAutoCloseableComponent();
- container.add(component);
-
- container.execute();
-
- assertThat(component.isStopped).isTrue();
- assertThat(component.isClosed).isTrue();
- assertThat(component.isClosedAfterStop).isTrue();
- }
-
- public static class StartableStoppableComponent implements Startable {
- public boolean started = false;
- public boolean stopped = false;
-
- @Override
- public void start() {
- started = true;
- }
-
- @Override
- public void stop() {
- stopped = true;
- }
- }
-
- public static class StartableStoppableApiComponent implements org.sonar.api.Startable {
- public boolean started = false;
- public boolean stopped = false;
-
- @Override
- public void start() {
- started = true;
- }
-
- @Override
- public void stop() {
- stopped = true;
- }
- }
-
- public static class ReflectionStartableStoppableComponent {
- public boolean started = false;
- public boolean stopped = false;
-
- public void start() {
- started = true;
- }
-
- public void stop() {
- stopped = true;
- }
- }
-
- public static class UnstartableComponent implements Startable {
- @Override
- public void start() {
- throw new IllegalStateException("Fail to start");
- }
-
- @Override
- public void stop() {
-
- }
- }
-
- public static class UnstartableApiComponent implements org.sonar.api.Startable {
- @Override
- public void start() {
- throw new IllegalStateException("Fail to start");
- }
-
- @Override
- public void stop() {
-
- }
- }
-
- public static class FailingStopWithISEComponent extends StartableStoppableComponent {
- public void stop() {
- super.stop();
- throw new IllegalStateException("Faking IllegalStateException thrown by stop method of " + getClass().getSimpleName());
- }
- }
-
- public static class FailingStopWithISEComponent2 extends FailingStopWithErrorComponent {
- }
-
- public static class FailingStopWithErrorComponent extends StartableStoppableComponent {
- public void stop() {
- super.stop();
- throw new Error("Faking Error thrown by stop method of " + getClass().getSimpleName());
- }
- }
-
- public static class FailingStopWithErrorComponent2 extends FailingStopWithErrorComponent {
- }
-
- public static class FailingStopWithOOMComponent extends StartableStoppableComponent {
- public void stop() {
- super.stop();
- consumeAvailableMemory();
- }
-
- private static List<Object> consumeAvailableMemory() {
- List<Object> holder = new ArrayList<>();
- while (true) {
- holder.add(new byte[128 * 1024]);
- }
- }
- }
-
- public static class FailingStopWithOOMComponent2 extends FailingStopWithOOMComponent {
-
- }
-
- @Property(key = "foo", defaultValue = "bar", name = "Foo")
- public static class ComponentWithProperty {
-
- }
-
- public static class SimpleComponent {
-
- }
-
- public static class SimpleComponentProvider extends ProviderAdapter {
- public SimpleComponent provide() {
- return new SimpleComponent();
- }
- }
-
- public static class CloseableComponent implements AutoCloseable {
- public boolean isClosed = false;
-
- @Override
- public void close() {
- isClosed = true;
- }
- }
-
- public static class StartableAutoCloseableComponent implements Startable,AutoCloseable {
- public boolean isClosed = false;
- public boolean isStopped = false;
- public boolean isClosedAfterStop = false;
-
- @Override
- public void start() {
- // nothing to do
- }
-
- @Override
- public void stop() {
- isStopped = true;
- }
-
- @Override
- public void close() {
- isClosed = true;
- isClosedAfterStop = isStopped;
- }
- }
-
- public static class StartableCloseableComponent implements Startable, Closeable {
- public boolean isClosed = false;
- public boolean isStopped = false;
- public boolean isClosedAfterStop = false;
-
- @Override
- public void start() {
- // nothing to do
- }
-
- @Override
- public void stop() {
- isStopped = true;
- }
-
- @Override
- public void close() {
- isClosed = true;
- isClosedAfterStop = isStopped;
- }
- }
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import org.junit.Test;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class LazyUnlessStartableStrategyTest {
+ private final LazyUnlessStartableStrategy postProcessor = new LazyUnlessStartableStrategy();
+
+ @Test
+ public void sets_all_beans_lazy() {
+ DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
+ beanFactory.registerBeanDefinition("bean1", new RootBeanDefinition());
+ assertThat(beanFactory.getBeanDefinition("bean1").isLazyInit()).isFalse();
+
+ postProcessor.postProcessBeanFactory(beanFactory);
+ assertThat(beanFactory.getBeanDefinition("bean1").isLazyInit()).isTrue();
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import java.util.Arrays;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.mock;
+
+public class ListContainerTest {
+
+ @Test
+ public void register_beans() {
+ ListContainer container = new ListContainer();
+ container.add(
+ A.class,
+ new VirtualModule(),
+ Arrays.asList(C.class, D.class)
+ );
+ assertThat(container.getAddedObjects()).contains(A.class, B.class, C.class, D.class);
+ }
+
+ @Test
+ public void addExtension_register_beans() {
+ ListContainer container = new ListContainer();
+ container
+ .addExtension("A", A.class)
+ .addExtension("B", B.class);
+ assertThat(container.getAddedObjects()).contains(A.class, B.class);
+ }
+
+ @Test
+ public void declareExtension_does_nothing() {
+ ListContainer container = new ListContainer();
+ assertThatNoException().isThrownBy(() -> container
+ .declareExtension("A", A.class)
+ .declareExtension(mock(PluginInfo.class), B.class));
+ }
+
+ @Test
+ public void unsupported_method_should_throw_exception() {
+ ListContainer container = new ListContainer();
+ container.add(A.class);
+ assertThatThrownBy(() -> container.getComponentByType(A.class)).isInstanceOf(UnsupportedOperationException.class);
+ assertThatThrownBy(() -> container.getOptionalComponentByType(A.class)).isInstanceOf(UnsupportedOperationException.class);
+ assertThatThrownBy(() -> container.getComponentsByType(A.class)).isInstanceOf(UnsupportedOperationException.class);
+ assertThatThrownBy(container::getParent).isInstanceOf(UnsupportedOperationException.class);
+ }
+
+ class A {
+ }
+
+ class B {
+ }
+
+ class C {
+ }
+
+ class D {
+ }
+
+ class VirtualModule extends Module {
+
+ @Override protected void configureModule() {
+ add(B.class);
+ }
+ }
+
+}
import static org.assertj.core.api.Assertions.assertThat;
public class ModuleTest {
- ComponentContainer container = new ComponentContainer();
- int initialSize = sizeOf(container);
+ private final ListContainer container = new ListContainer();
@Test(expected = NullPointerException.class)
public void configure_throws_NPE_if_container_is_empty() {
}
}.configure(container);
- assertThat(sizeOf(container)).isSameAs(initialSize);
+ assertThat(container.getAddedObjects()).isEmpty();
}
@Test
}
}.configure(container);
- assertThat(sizeOf(container)).isEqualTo(initialSize);
+ assertThat(container.getAddedObjects()).isEmpty();
}
@Test
}
}.configure(container);
- assertThat(sizeOf(container)).isEqualTo(initialSize + 2);
+ assertThat(container.getAddedObjects()).hasSize(2);
}
- private static int sizeOf(ComponentContainer container) {
- return container.getPicoContainer().getComponentAdapters().size();
+ private static int sizeOf(SpringComponentContainer container) {
+ return container.context.getBeanDefinitionCount();
}
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.core.platform;
-
-import java.lang.reflect.Method;
-import org.junit.Test;
-import org.picocontainer.Characteristics;
-import org.picocontainer.MutablePicoContainer;
-import org.picocontainer.PicoLifecycleException;
-import org.picocontainer.Startable;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-
-public class PicoUtilsTest {
-
- @Test
- public void shouldSanitizePicoLifecycleException() throws NoSuchMethodException {
- UncheckedFailureComponent instance = new UncheckedFailureComponent();
- Method method = UncheckedFailureComponent.class.getMethod("start");
- try {
- instance.start();
- fail("Start should have thrown a IllegalStateException");
- }
- catch (IllegalStateException e) {
- Throwable th = PicoUtils.sanitize(new PicoLifecycleException(method, instance, e));
-
- assertThat(th).isInstanceOf(IllegalStateException.class);
- assertThat(th.getMessage()).isEqualTo("A good reason to fail");
- }
- }
-
- @Test
- public void shouldSanitizePicoLifecycleException_no_wrapper_message() {
- Throwable th = PicoUtils.sanitize(new PicoLifecycleException(null, null, new IllegalStateException("msg")));
-
- assertThat(th).isInstanceOf(IllegalStateException.class);
- assertThat(th.getMessage()).isEqualTo("msg");
- }
-
- @Test
- public void shouldNotSanitizeOtherExceptions() {
- Throwable th = PicoUtils.sanitize(new IllegalArgumentException("foo"));
-
- assertThat(th).isInstanceOf(IllegalArgumentException.class);
- assertThat(th.getMessage()).isEqualTo("foo");
- }
-
- @Test
- public void shouldPropagateInitialUncheckedException() {
- try {
- PicoUtils.propagate(newPicoLifecycleException());
- fail();
- } catch (RuntimeException e) {
- assertThat(e).isInstanceOf(IllegalStateException.class);
- }
- }
-
-
- private PicoLifecycleException newPicoLifecycleException() {
- MutablePicoContainer container = ComponentContainer.createPicoContainer().as(Characteristics.CACHE);
- container.addComponent(UncheckedFailureComponent.class);
- try {
- container.start();
- throw new IllegalStateException("An exception should have been thrown by start()");
-
- } catch (PicoLifecycleException e) {
- return e;
- }
- }
-
- public static class UncheckedFailureComponent implements Startable {
- public void start() {
- throw new IllegalStateException("A good reason to fail");
- }
-
- @Override
- public void stop() {
- // nothing to do
- }
- }
-
-}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import javax.annotation.Priority;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
+import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.core.annotation.AnnotationAwareOrderComparator;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class PriorityBeanFactoryTest {
+ private final DefaultListableBeanFactory parentBeanFactory = new PriorityBeanFactory();
+ private final DefaultListableBeanFactory beanFactory = new PriorityBeanFactory();
+
+ @Before
+ public void setUp() {
+ // needed to support autowiring with @Inject
+ beanFactory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
+ //needed to read @Priority
+ beanFactory.setDependencyComparator(new AnnotationAwareOrderComparator());
+ beanFactory.setParentBeanFactory(parentBeanFactory);
+ }
+
+ @Test
+ public void give_priority_to_child_container() {
+ parentBeanFactory.registerBeanDefinition("A1", new RootBeanDefinition(A1.class));
+
+ beanFactory.registerBeanDefinition("A2", new RootBeanDefinition(A2.class));
+ beanFactory.registerBeanDefinition("B", new RootBeanDefinition(B.class));
+
+ assertThat(beanFactory.getBean(B.class).dep.getClass()).isEqualTo(A2.class);
+ }
+
+ @Test
+ public void follow_priority_annotations() {
+ parentBeanFactory.registerBeanDefinition("A3", new RootBeanDefinition(A3.class));
+
+ beanFactory.registerBeanDefinition("A1", new RootBeanDefinition(A1.class));
+ beanFactory.registerBeanDefinition("A2", new RootBeanDefinition(A2.class));
+ beanFactory.registerBeanDefinition("B", new RootBeanDefinition(B.class));
+
+ assertThat(beanFactory.getBean(B.class).dep.getClass()).isEqualTo(A3.class);
+ }
+
+ @Test
+ public void throw_NoUniqueBeanDefinitionException_if_cant_find_single_bean_with_higher_priority() {
+ beanFactory.registerBeanDefinition("A1", new RootBeanDefinition(A1.class));
+ beanFactory.registerBeanDefinition("A2", new RootBeanDefinition(A2.class));
+ beanFactory.registerBeanDefinition("B", new RootBeanDefinition(B.class));
+
+ assertThatThrownBy(() -> beanFactory.getBean(B.class))
+ .hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class);
+ }
+
+ private static class B {
+ private final A dep;
+
+ public B(A dep) {
+ this.dep = dep;
+ }
+ }
+
+ private interface A {
+
+ }
+
+ private static class A1 implements A {
+
+ }
+
+ private static class A2 implements A {
+
+ }
+
+ @Priority(1)
+ private static class A3 implements A {
+
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import java.util.Arrays;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import org.junit.Test;
+import org.sonar.api.Property;
+import org.sonar.api.Startable;
+import org.sonar.api.config.PropertyDefinition;
+import org.sonar.api.config.PropertyDefinitions;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertThrows;
+
+public class SpringComponentContainerTest {
+ @Test
+ public void should_stop_after_failing() {
+ ApiStartable startStop = new ApiStartable();
+ SpringComponentContainer container = new SpringComponentContainer() {
+ @Override
+ public void doBeforeStart() {
+ add(startStop);
+ }
+
+ @Override
+ public void doAfterStart() {
+ getComponentByType(ApiStartable.class);
+ throw new IllegalStateException("doBeforeStart");
+ }
+ };
+
+ assertThrows("doBeforeStart", IllegalStateException.class, container::execute);
+ assertThat(startStop.start).isOne();
+ assertThat(startStop.stop).isOne();
+ }
+
+ @Test
+ public void add_registers_instance_with_toString() {
+ SpringComponentContainer container = new SimpleContainer(new ToString("a"), new ToString("b"));
+ container.startComponents();
+ assertThat(container.context.getBeanDefinitionNames())
+ .contains(
+ this.getClass().getClassLoader() + "-org.sonar.core.platform.SpringComponentContainerTest.ToString-a",
+ this.getClass().getClassLoader() + "-org.sonar.core.platform.SpringComponentContainerTest.ToString-b");
+ assertThat(container.getComponentsByType(ToString.class)).hasSize(2);
+ }
+
+ @Test
+ public void add_registers_class_with_classloader_and_fqcn() {
+ SpringComponentContainer container = new SimpleContainer(A.class, B.class);
+ container.startComponents();
+ assertThat(container.context.getBeanDefinitionNames())
+ .contains(
+ this.getClass().getClassLoader() + "-org.sonar.core.platform.SpringComponentContainerTest.A",
+ this.getClass().getClassLoader() + "-org.sonar.core.platform.SpringComponentContainerTest.B");
+ assertThat(container.getComponentByType(A.class)).isNotNull();
+ assertThat(container.getComponentByType(B.class)).isNotNull();
+ }
+
+ @Test
+ public void add_configures_module_instances() {
+ SpringComponentContainer container = new SpringComponentContainer();
+ container.add(new TestModule());
+ container.startComponents();
+ assertThat(container.getComponentByType(A.class)).isNotNull();
+ }
+
+ @Test
+ public void get_optional_component_by_type_should_return_correctly() {
+ SpringComponentContainer container = new SpringComponentContainer();
+ container.add(A.class);
+ container.startComponents();
+ assertThat(container.getOptionalComponentByType(A.class)).containsInstanceOf(A.class);
+ assertThat(container.getOptionalComponentByType(B.class)).isEmpty();
+ }
+
+ @Test
+ public void createChild_method_should_spawn_a_child_container(){
+ SpringComponentContainer parent = new SpringComponentContainer();
+ SpringComponentContainer child = parent.createChild();
+ assertThat(child).isNotEqualTo(parent);
+ assertThat(child.parent).isEqualTo(parent);
+ assertThat(parent.children).contains(child);
+ }
+
+ @Test
+ public void get_component_by_type_should_throw_exception_when_type_does_not_exist() {
+ SpringComponentContainer container = new SpringComponentContainer();
+ container.add(A.class);
+ container.startComponents();
+ assertThatThrownBy(() -> container.getComponentByType(B.class))
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessage("Unable to load component class org.sonar.core.platform.SpringComponentContainerTest$B");
+ }
+
+ @Test
+ public void add_fails_if_adding_module_class() {
+ SpringComponentContainer container = new SpringComponentContainer();
+ container.startComponents();
+ assertThatThrownBy(() -> container.add(TestModule.class))
+ .hasMessage("Modules should be added as instances")
+ .isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ public void should_throw_start_exception_if_stop_also_throws_exception() {
+ ErrorStopClass errorStopClass = new ErrorStopClass();
+ SpringComponentContainer container = new SpringComponentContainer() {
+ @Override
+ public void doBeforeStart() {
+ add(errorStopClass);
+ }
+
+ @Override
+ public void doAfterStart() {
+ getComponentByType(ErrorStopClass.class);
+ throw new IllegalStateException("doBeforeStart");
+ }
+ };
+ assertThrows("doBeforeStart", IllegalStateException.class, container::execute);
+ assertThat(errorStopClass.stopped).isTrue();
+ }
+
+ @Test
+ public void addExtension_supports_extensions_without_annotations() {
+ SpringComponentContainer container = new SimpleContainer(A.class, B.class);
+ container.addExtension("", ExtensionWithMultipleConstructorsAndNoAnnotations.class);
+ container.startComponents();
+ assertThat(container.getComponentByType(ExtensionWithMultipleConstructorsAndNoAnnotations.class).gotBothArgs).isTrue();
+ }
+
+ @Test
+ public void addExtension_supports_extension_instances_without_annotations() {
+ SpringComponentContainer container = new SpringComponentContainer();
+ container.addExtension("", new ExtensionWithMultipleConstructorsAndNoAnnotations(new A()));
+ container.startComponents();
+ assertThat(container.getComponentByType(ExtensionWithMultipleConstructorsAndNoAnnotations.class)).isNotNull();
+ }
+
+ @Test
+ public void addExtension_resolves_iterables() {
+ List<Class<?>> classes = Arrays.asList(A.class, B.class);
+ SpringComponentContainer container = new SpringComponentContainer();
+ container.addExtension("", classes);
+ container.startComponents();
+ assertThat(container.getComponentByType(A.class)).isNotNull();
+ assertThat(container.getComponentByType(B.class)).isNotNull();
+ }
+
+ @Test
+ public void addExtension_adds_property_with_PluginInfo() {
+ PluginInfo info = new PluginInfo("plugin1").setName("plugin1");
+ SpringComponentContainer container = new SpringComponentContainer();
+ container.addExtension(info, A.class);
+
+ container.startComponents();
+ PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
+ PropertyDefinition propertyDefinition = propertyDefinitions.get("k");
+ assertThat(propertyDefinition.key()).isEqualTo("k");
+ assertThat(propertyDefinitions.getCategory("k")).isEqualTo("plugin1");
+ }
+
+ @Test
+ public void declareExtension_adds_property() {
+ SpringComponentContainer container = new SpringComponentContainer();
+ container.addExtension((PluginInfo) null, A.class);
+
+ container.startComponents();
+ PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
+ PropertyDefinition propertyDefinition = propertyDefinitions.get("k");
+ assertThat(propertyDefinition.key()).isEqualTo("k");
+ assertThat(propertyDefinitions.getCategory("k")).isEmpty();
+ }
+
+ @Test
+ public void stop_should_stop_children() {
+ SpringComponentContainer parent = new SpringComponentContainer();
+ ApiStartable s1 = new ApiStartable();
+ parent.add(s1);
+ parent.startComponents();
+ SpringComponentContainer child = new SpringComponentContainer(parent);
+ assertThat(child.getParent()).isEqualTo(parent);
+ assertThat(parent.children).containsOnly(child);
+ ApiStartable s2 = new ApiStartable();
+ child.add(s2);
+ child.startComponents();
+
+ parent.stopComponents();
+ assertThat(s1.stop).isOne();
+ assertThat(s2.stop).isOne();
+ }
+
+ @Test
+ public void stop_should_remove_container_from_parent() {
+ SpringComponentContainer parent = new SpringComponentContainer();
+ SpringComponentContainer child = new SpringComponentContainer(parent);
+ assertThat(parent.children).containsOnly(child);
+ child.stopComponents();
+ assertThat(parent.children).isEmpty();
+ }
+
+ @Test
+ public void bean_create_fails_if_class_has_default_constructor_and_other_constructors() {
+ SpringComponentContainer container = new SpringComponentContainer();
+ container.add(ClassWithMultipleConstructorsIncNoArg.class);
+ container.startComponents();
+ assertThatThrownBy(() -> container.getComponentByType(ClassWithMultipleConstructorsIncNoArg.class))
+ .hasRootCauseMessage("Constructor annotations missing in: class org.sonar.core.platform.SpringComponentContainerTest$ClassWithMultipleConstructorsIncNoArg");
+ }
+
+ @Test
+ public void support_start_stop_callbacks() {
+ JsrLifecycleCallbacks jsr = new JsrLifecycleCallbacks();
+ ApiStartable api = new ApiStartable();
+ AutoClose closeable = new AutoClose();
+
+ SpringComponentContainer container = new SimpleContainer(jsr, api, closeable) {
+ @Override
+ public void doAfterStart() {
+ // force lazy instantiation
+ getComponentByType(JsrLifecycleCallbacks.class);
+ getComponentByType(ApiStartable.class);
+ getComponentByType(AutoClose.class);
+ }
+ };
+ container.execute();
+
+ assertThat(closeable.closed).isOne();
+ assertThat(jsr.postConstruct).isOne();
+ assertThat(jsr.preDestroy).isOne();
+ assertThat(api.start).isOne();
+ assertThat(api.stop).isOne();
+ }
+
+ private static class TestModule extends Module {
+ @Override
+ protected void configureModule() {
+ add(A.class);
+ }
+ }
+
+ private static class JsrLifecycleCallbacks {
+ private int postConstruct = 0;
+ private int preDestroy = 0;
+
+ @PostConstruct
+ public void postConstruct() {
+ postConstruct++;
+ }
+
+ @PreDestroy
+ public void preDestroy() {
+ preDestroy++;
+ }
+ }
+
+ private static class AutoClose implements AutoCloseable {
+ private int closed = 0;
+
+ @Override
+ public void close() {
+ closed++;
+ }
+ }
+
+ private static class ApiStartable implements Startable {
+ private int start = 0;
+ private int stop = 0;
+
+ public void start() {
+ start++;
+ }
+
+ public void stop() {
+ stop++;
+ }
+ }
+
+ private static class ToString {
+ private final String toString;
+
+ public ToString(String toString) {
+ this.toString = toString;
+ }
+
+ @Override
+ public String toString() {
+ return toString;
+ }
+ }
+
+ @Property(key = "k", name = "name")
+ private static class A {
+ }
+
+ private static class B {
+ }
+
+ private static class ClassWithMultipleConstructorsIncNoArg {
+ public ClassWithMultipleConstructorsIncNoArg() {
+ }
+
+ public ClassWithMultipleConstructorsIncNoArg(A a) {
+ }
+ }
+
+ private static class ExtensionWithMultipleConstructorsAndNoAnnotations {
+ private boolean gotBothArgs = false;
+
+ public ExtensionWithMultipleConstructorsAndNoAnnotations(A a) {
+ }
+
+ public ExtensionWithMultipleConstructorsAndNoAnnotations(A a, B b) {
+ gotBothArgs = true;
+ }
+ }
+
+ private static class ErrorStopClass implements Startable {
+ private boolean stopped = false;
+
+ @Override
+ public void start() {
+ }
+
+ @Override
+ public void stop() {
+ stopped = true;
+ throw new IllegalStateException("stop");
+ }
+ }
+
+ private static class SimpleContainer extends SpringComponentContainer {
+ public SimpleContainer(Object... objects) {
+ add(objects);
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import org.junit.Test;
+import org.sonar.api.Startable;
+
+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;
+
+public class StartableBeanPostProcessorTest {
+ private final StartableBeanPostProcessor underTest = new StartableBeanPostProcessor();
+
+ @Test
+ public void starts_api_startable() {
+ Startable startable = mock(Startable.class);
+ underTest.postProcessBeforeInitialization(startable, "startable");
+ verify(startable).start();
+ verifyNoMoreInteractions(startable);
+ }
+
+ @Test
+ public void stops_api_startable() {
+ Startable startable = mock(Startable.class);
+ underTest.postProcessBeforeDestruction(startable, "startable");
+ verify(startable).stop();
+ verifyNoMoreInteractions(startable);
+ }
+
+ @Test
+ public void startable_and_autoCloseable_should_require_destruction(){
+ assertThat(underTest.requiresDestruction(mock(Startable.class))).isTrue();
+ assertThat(underTest.requiresDestruction(mock(org.sonar.api.Startable.class))).isTrue();
+ assertThat(underTest.requiresDestruction(mock(Object.class))).isFalse();
+ }
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.core.platform;
-
-import java.io.Closeable;
-import java.io.IOException;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.Startable;
-import org.sonar.api.utils.log.LogTester;
-import org.sonar.api.utils.log.LoggerLevel;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-public class StartableCloseableSafeLifecyleStrategyTest {
- @Rule
- public LogTester logTester = new LogTester();
-
- private StartableCloseableSafeLifecyleStrategy underTest = new StartableCloseableSafeLifecyleStrategy();
-
- @Test
- public void start_calls_start_on_Startable_subclass() {
- Startable startable = mock(Startable.class);
-
- underTest.start(startable);
-
- verify(startable).start();
- verifyNoMoreInteractions(startable);
- }
-
- @Test
- public void start_calls_start_on_api_Startable_subclass() {
- org.picocontainer.Startable startable = mock(org.picocontainer.Startable.class);
-
- underTest.start(startable);
-
- verify(startable).start();
- verifyNoMoreInteractions(startable);
- }
-
- @Test
- public void start_does_not_call_stop_on_class_with_method_start_not_implementing_startable() {
- Object startable = spy(new Object() {
- public void start() {
- // nothing to do
- }
- });
-
- underTest.start(startable);
-
- verifyNoMoreInteractions(startable);
- }
-
- @Test
- public void stop_calls_stop_on_Startable_subclass() {
- Startable startable = mock(Startable.class);
-
- underTest.stop(startable);
-
- verify(startable).stop();
- verifyNoMoreInteractions(startable);
- }
-
- @Test
- public void stop_calls_stop_on_api_Startable_subclass() {
- org.picocontainer.Startable startable = mock(org.picocontainer.Startable.class);
-
- underTest.stop(startable);
-
- verify(startable).stop();
- verifyNoMoreInteractions(startable);
- }
-
- @Test
- public void stop_does_not_call_stop_on_class_with_method_stop_not_implementing_startable() {
- Object startable = spy(new Object() {
- public void stop() {
- // nothing to do
- }
- });
-
- underTest.stop(startable);
-
- verifyNoMoreInteractions(startable);
- }
-
- @Test
- public void dispose_calls_close_on_Closeable_subclass() throws IOException {
- Closeable closeable = mock(Closeable.class);
-
- underTest.dispose(closeable);
-
- verify(closeable).close();
- verifyNoMoreInteractions(closeable);
- }
-
- @Test
- public void dispose_calls_close_on_AutoCloseable_subclass() throws Exception {
- AutoCloseable autoCloseable = mock(AutoCloseable.class);
-
- underTest.dispose(autoCloseable);
-
- verify(autoCloseable).close();
- verifyNoMoreInteractions(autoCloseable);
- }
-
- @Test
- public void dispose_does_not_call_close_on_class_with_method_close_not_implementing_Closeable_nor_AutoCloseable() {
- Object closeable = spy(new Object() {
- public void close() {
- // nothing to do
- }
- });
-
- underTest.dispose(closeable);
-
- verifyNoMoreInteractions(closeable);
- }
-
- @Test
- public void hasLifecycle_returns_true_on_Startable_and_subclass() {
- Startable startable = mock(Startable.class);
-
- assertThat(underTest.hasLifecycle(Startable.class)).isTrue();
- assertThat(underTest.hasLifecycle(startable.getClass())).isTrue();
- }
-
- @Test
- public void hasLifecycle_returns_true_on_api_Startable_and_subclass() {
- org.picocontainer.Startable startable = mock(org.picocontainer.Startable.class);
-
- assertThat(underTest.hasLifecycle(org.picocontainer.Startable.class)).isTrue();
- assertThat(underTest.hasLifecycle(startable.getClass())).isTrue();
- }
-
- @Test
- public void hasLifecycle_returns_true_on_api_Closeable_and_subclass() {
- Closeable closeable = mock(Closeable.class);
-
- assertThat(underTest.hasLifecycle(Closeable.class)).isTrue();
- assertThat(underTest.hasLifecycle(closeable.getClass())).isTrue();
- }
-
- @Test
- public void hasLifecycle_returns_true_on_api_AutoCloseable_and_subclass() {
- AutoCloseable autoCloseable = mock(AutoCloseable.class);
-
- assertThat(underTest.hasLifecycle(AutoCloseable.class)).isTrue();
- assertThat(underTest.hasLifecycle(autoCloseable.getClass())).isTrue();
- }
-
- @Test
- public void hasLifeCycle_returns_false_and_log_a_warning_for_type_defining_start_without_implementating_Startable() {
- Object startable = new Object() {
- public void start() {
- // nothing to do
- }
- };
-
- assertThat(underTest.hasLifecycle(startable.getClass())).isFalse();
- verifyWarnLog(startable.getClass());
- }
-
- @Test
- public void hasLifeCycle_returns_false_and_log_a_warning_for_type_defining_stop_without_implementating_Startable() {
- Object startable = new Object() {
- public void stop() {
- // nothing to do
- }
- };
-
- assertThat(underTest.hasLifecycle(startable.getClass())).isFalse();
- verifyWarnLog(startable.getClass());
- }
-
- private void verifyWarnLog(Class<?> type) {
- assertThat(logTester.logs()).hasSize(1);
- assertThat(logTester.logs(LoggerLevel.WARN))
- .contains("Component of type class " + type.getName() + " defines methods start() and/or stop(). Neither will be invoked to start/stop the component. " +
- "Please implement either org.picocontainer.Startable or org.sonar.api.Startable");
- }
-
- @Test
- public void hasLifeCycle_returns_false_and_log_a_warning_for_type_defining_close_without_implementating_Closeable_nor_AutoCloseable() {
- Object startable = new Object() {
- public void close() {
- // nothing to do
- }
- };
-
- assertThat(underTest.hasLifecycle(startable.getClass())).isFalse();
- assertThat(logTester.logs()).hasSize(1);
- assertThat(logTester.logs(LoggerLevel.WARN))
- .contains("Component of type class " + startable.getClass().getName() + " defines method close(). It won't be invoked to dispose the component. " +
- "Please implement either java.io.Closeable or java.lang.AutoCloseable");
- }
-}
*/
package org.sonar.api.resources;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
import org.apache.commons.lang.ArrayUtils;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* A class to store the list of languages
*
compile 'javax.annotation:javax.annotation-api'
compile 'org.eclipse.jgit:org.eclipse.jgit'
compile 'org.tmatesoft.svnkit:svnkit'
- compile 'org.picocontainer:picocontainer'
compile 'org.slf4j:jcl-over-slf4j'
compile 'org.slf4j:jul-to-slf4j'
compile 'org.slf4j:log4j-over-slf4j'
testCompile 'org.mockito:mockito-core'
testCompile project(':plugins:sonar-xoo-plugin')
testCompile project(':sonar-plugin-api').sourceSets.test.output
-
}
license {
public class AnalysisTempFolderProvider {
static final String TMP_NAME = ".sonartmp";
- @Bean("TempFolder")
+ @Bean("AnalysisTempFolder")
public TempFolder provide(DefaultInputProject project) {
Path workingDir = project.getWorkDir();
Path tempDir = workingDir.normalize().resolve(TMP_NAME);
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.scanner.bootstrap;
-
-import java.lang.reflect.Constructor;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.lang.Nullable;
-
-/**
- * Taken from Spring's GenericApplicationContext.ClassDerivedBeanDefinition.
- */
-public class ClassDerivedBeanDefinition extends RootBeanDefinition {
- public ClassDerivedBeanDefinition(Class<?> beanClass) {
- super(beanClass);
- }
-
- public ClassDerivedBeanDefinition(ClassDerivedBeanDefinition original) {
- super(original);
- }
-
- /**
- * This method gets called from AbstractAutowireCapableBeanFactory#createBeanInstance when a bean is instantiated.
- * It first tries to look at annotations or any other methods provided by bean post processors. If a constructor can't be determined, it will fallback to this method.
- */
- @Override
- @Nullable
- public Constructor<?>[] getPreferredConstructors() {
- Class<?> clazz = getBeanClass();
- Constructor<?> primaryCtor = BeanUtils.findPrimaryConstructor(clazz);
- if (primaryCtor != null) {
- return new Constructor<?>[] {primaryCtor};
- }
- Constructor<?>[] publicCtors = clazz.getConstructors();
- if (publicCtors.length > 0) {
- return publicCtors;
- }
- return null;
- }
-
- @Override
- public RootBeanDefinition cloneBeanDefinition() {
- return new ClassDerivedBeanDefinition(this);
- }
-}
*/
package org.sonar.scanner.bootstrap;
-import java.io.IOException;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.CoreProperties;
-import org.sonar.api.Startable;
import org.sonar.api.impl.utils.DefaultTempFolder;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.TempFolder;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import static org.sonar.core.util.FileUtils.deleteQuietly;
import org.springframework.context.annotation.Bean;
-import static org.sonar.core.util.FileUtils.deleteQuietly;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.concurrent.TimeUnit;
-public class GlobalTempFolderProvider implements Startable {
+public class GlobalTempFolderProvider {
private static final Logger LOG = Loggers.get(GlobalTempFolderProvider.class);
private static final long CLEAN_MAX_AGE = TimeUnit.DAYS.toMillis(21);
static final String TMP_NAME_PREFIX = ".sonartmp_";
private System2 system;
- private DefaultTempFolder tempFolder;
public GlobalTempFolderProvider() {
this(new System2());
this.system = system;
}
- @Bean("TempFolder")
+ @Bean("GlobalTempFolder")
public TempFolder provide(ScannerProperties scannerProps) {
- if (tempFolder == null) {
- String workingPathName = StringUtils.defaultIfBlank(scannerProps.property(CoreProperties.GLOBAL_WORKING_DIRECTORY), CoreProperties.GLOBAL_WORKING_DIRECTORY_DEFAULT_VALUE);
- Path workingPath = Paths.get(workingPathName);
+ String workingPathName = StringUtils.defaultIfBlank(scannerProps.property(CoreProperties.GLOBAL_WORKING_DIRECTORY), CoreProperties.GLOBAL_WORKING_DIRECTORY_DEFAULT_VALUE);
+ Path workingPath = Paths.get(workingPathName);
- if (!workingPath.isAbsolute()) {
- Path home = findSonarHome(scannerProps);
- workingPath = home.resolve(workingPath).normalize();
- }
- try {
- cleanTempFolders(workingPath);
- } catch (IOException e) {
- LOG.error(String.format("failed to clean global working directory: %s", workingPath), e);
- }
- Path tempDir = createTempFolder(workingPath);
- tempFolder = new DefaultTempFolder(tempDir.toFile(), true);
+ if (!workingPath.isAbsolute()) {
+ Path home = findSonarHome(scannerProps);
+ workingPath = home.resolve(workingPath).normalize();
}
- return tempFolder;
+ try {
+ cleanTempFolders(workingPath);
+ } catch (IOException e) {
+ LOG.error(String.format("failed to clean global working directory: %s", workingPath), e);
+ }
+ Path tempDir = createTempFolder(workingPath);
+ return new DefaultTempFolder(tempDir.toFile(), true);
+
}
private static Path createTempFolder(Path workingPath) {
}
}
- @Override
- public void start() {
- // nothing to do
- }
-
- @Override
- public void stop() {
- if (tempFolder != null) {
- tempFolder.stop();
- }
- }
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.scanner.bootstrap;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-
-public class LazyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- for (String beanName : beanFactory.getBeanDefinitionNames()) {
- BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
- beanDefinition.setLazyInit(true);
- }
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.scanner.bootstrap;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.springframework.beans.factory.support.DefaultListableBeanFactory;
-
-public class PriorityBeanFactory extends DefaultListableBeanFactory {
- /**
- * Determines highest priority of the bean candidates.
- * Does not take into account the @Primary annotations.
- * This gets called from {@link DefaultListableBeanFactory#determineAutowireCandidate} when the bean factory is finding the beans to autowire. That method
- * checks for @Primary before calling this method.
- *
- * The strategy is to look at the @Priority annotations. If there are ties, we give priority to components that were added to child containers over their parents.
- * If there are still ties, null is returned, which will ultimately cause Spring to throw a NoUniqueBeanDefinitionException.
- */
- @Override
- @Nullable
- protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
- List<Bean> candidateBeans = candidates.entrySet().stream()
- .filter(e -> e.getValue() != null)
- .map(e -> new Bean(e.getKey(), e.getValue()))
- .collect(Collectors.toUnmodifiableList());
-
- List<Bean> beansAfterPriority = highestPriority(candidateBeans, b -> getPriority(b.getInstance()));
- if (beansAfterPriority.isEmpty()) {
- return null;
- } else if (beansAfterPriority.size() == 1) {
- return beansAfterPriority.get(0).getName();
- }
-
- List<Bean> beansAfterHierarchy = highestPriority(beansAfterPriority, b -> getHierarchyPriority(b.getName()));
- if (beansAfterHierarchy.size() == 1) {
- return beansAfterHierarchy.get(0).getName();
- }
-
- return null;
- }
-
- private static List<Bean> highestPriority(List<Bean> candidates, PriorityFunction function) {
- List<Bean> highestPriorityBeans = new ArrayList<>();
- Integer highestPriority = null;
-
- for (Bean candidate : candidates) {
- Integer candidatePriority = function.classify(candidate);
- if (candidatePriority == null) {
- candidatePriority = Integer.MAX_VALUE;
- }
- if (highestPriority == null) {
- highestPriority = candidatePriority;
- highestPriorityBeans.add(candidate);
- } else if (candidatePriority < highestPriority) {
- highestPriorityBeans.clear();
- highestPriority = candidatePriority;
- highestPriorityBeans.add(candidate);
- } else if (candidatePriority.equals(highestPriority)) {
- highestPriorityBeans.add(candidate);
- }
- }
- return highestPriorityBeans;
- }
-
- @CheckForNull
- private Integer getHierarchyPriority(String beanName) {
- DefaultListableBeanFactory factory = this;
- int i = 1;
- while (factory != null) {
- if (factory.containsBeanDefinition(beanName)) {
- return i;
- }
- factory = (DefaultListableBeanFactory) factory.getParentBeanFactory();
- i++;
- }
- return null;
- }
-
- private static class Bean {
- private final String name;
- private final Object instance;
-
- public Bean(String name, Object instance) {
- this.name = name;
- this.instance = instance;
- }
-
- public String getName() {
- return name;
- }
-
- public Object getInstance() {
- return instance;
- }
- }
-
- @FunctionalInterface
- private interface PriorityFunction {
- @Nullable
- Integer classify(Bean candidate);
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.scanner.bootstrap;
-
-import com.google.common.collect.Iterables;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Supplier;
-import javax.annotation.CheckForNull;
-import org.jetbrains.annotations.Nullable;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.utils.System2;
-import org.sonar.core.platform.ComponentKeys;
-import org.sonar.core.platform.Container;
-import org.sonar.core.platform.ExtensionContainer;
-import org.sonar.core.platform.PluginInfo;
-import org.springframework.context.annotation.AnnotationConfigApplicationContext;
-
-import static java.util.Collections.emptyList;
-import static java.util.Optional.ofNullable;
-
-public class SpringComponentContainer implements ExtensionContainer {
- protected final AnnotationConfigApplicationContext context;
- @Nullable
- protected final SpringComponentContainer parent;
-
- private final PropertyDefinitions propertyDefinitions;
- private final ComponentKeys componentKeys = new ComponentKeys();
-
- protected SpringComponentContainer() {
- this(null, new PropertyDefinitions(System2.INSTANCE), emptyList());
- }
-
- protected SpringComponentContainer(List<?> externalExtensions) {
- this(null, new PropertyDefinitions(System2.INSTANCE), externalExtensions);
- }
-
- protected SpringComponentContainer(SpringComponentContainer parent) {
- this(parent, parent.propertyDefinitions, emptyList());
- }
-
- private SpringComponentContainer(@Nullable SpringComponentContainer parent, PropertyDefinitions propertyDefinitions, List<?> externalExtensions) {
- this.parent = parent;
- this.propertyDefinitions = propertyDefinitions;
- this.context = new AnnotationConfigApplicationContext(new PriorityBeanFactory());
- if (parent != null) {
- context.setParent(parent.context);
- }
- add(this);
- add(new StartableBeanPostProcessor());
- add(externalExtensions);
- add(propertyDefinitions);
- }
-
- /**
- * Beans need to have a unique name, otherwise they'll override each other.
- * The strategy is:
- * - For classes, use the classloader + fully qualified class name as the name of the bean
- * - For instances, use the Classloader + FQCN + toString()
- * - If the object is a collection, iterate through the elements and apply the same strategy for each of them
- */
- @Override
- public Container add(Object... objects) {
- for (Object o : objects) {
- if (o instanceof Class) {
- Class<?> clazz = (Class<?>) o;
- context.registerBean(componentKeys.ofClass(clazz), clazz);
- } else if (o instanceof Iterable) {
- add(Iterables.toArray((Iterable<?>) o, Object.class));
- } else {
- registerInstance(o);
- }
- }
- return this;
- }
-
- private <T> void registerInstance(T instance) {
- Supplier<T> supplier = () -> instance;
- Class<T> clazz = (Class<T>) instance.getClass();
- context.registerBean(componentKeys.ofInstance(instance), clazz, supplier);
- declareExtension("", instance);
- }
-
- /**
- * Extensions are usually added by plugins and we assume they don't support any injection-related annotations.
- * Spring contexts supporting annotations will fail if multiple constructors are present without any annotations indicating which one to use for injection.
- * For that reason, we need to create the beans ourselves, using ClassDerivedBeanDefinition, which will declare that all constructors can be used for injection.
- */
- private Container addExtension(Object o) {
- if (o instanceof Class) {
- Class<?> clazz = (Class<?>) o;
- ClassDerivedBeanDefinition bd = new ClassDerivedBeanDefinition(clazz);
- context.registerBeanDefinition(componentKeys.ofClass(clazz), bd);
- } else if (o instanceof Iterable) {
- ((Iterable<?>) o).forEach(this::addExtension);
- } else {
- ClassDerivedBeanDefinition bd = new ClassDerivedBeanDefinition(o.getClass());
- bd.setInstanceSupplier(() -> o);
- context.registerBeanDefinition(componentKeys.ofInstance(o), bd);
- }
- return this;
- }
-
- @Override
- public Container addSingletons(Iterable<?> components) {
- return add(components);
- }
-
- @Override
- public <T> T getComponentByType(Class<T> type) {
- try {
- return context.getBean(type);
- } catch (Exception t) {
- throw new IllegalStateException("Unable to load component " + type, t);
- }
- }
-
- @Override
- public <T> List<T> getComponentsByType(Class<T> type) {
- try {
- return new ArrayList<>(context.getBeansOfType(type).values());
- } catch (Exception t) {
- throw new IllegalStateException("Unable to load components " + type, t);
- }
- }
-
- public void execute() {
- RuntimeException r = null;
- try {
- startComponents();
- } catch (RuntimeException e) {
- r = e;
- } finally {
- try {
- stopComponents();
- } catch (RuntimeException e) {
- if (r == null) {
- r = e;
- }
- }
- }
- if (r != null) {
- throw r;
- }
- }
-
- public SpringComponentContainer startComponents() {
- doBeforeStart();
- context.refresh();
- doAfterStart();
- return this;
- }
-
- public SpringComponentContainer stopComponents() {
- if (context.isActive()) {
- context.close();
- }
- return this;
- }
-
- public SpringComponentContainer createChild() {
- return new SpringComponentContainer(this);
- }
-
- @Override
- @CheckForNull
- public SpringComponentContainer getParent() {
- return parent;
- }
-
- @Override
- public SpringComponentContainer addExtension(@Nullable PluginInfo pluginInfo, Object extension) {
- addExtension(extension);
- declareExtension(pluginInfo, extension);
- return this;
- }
-
- @Override
- public SpringComponentContainer addExtension(@Nullable String defaultCategory, Object extension) {
- addExtension(extension);
- declareExtension(defaultCategory, extension);
- return this;
- }
-
- @Override
- public SpringComponentContainer declareExtension(@Nullable PluginInfo pluginInfo, Object extension) {
- declareExtension(pluginInfo != null ? pluginInfo.getName() : "", extension);
- return this;
- }
-
- @Override
- public SpringComponentContainer declareExtension(@Nullable String defaultCategory, Object extension) {
- this.propertyDefinitions.addComponent(extension, ofNullable(defaultCategory).orElse(""));
- return this;
- }
-
- /**
- * This method aims to be overridden
- */
- protected void doBeforeStart() {
- // nothing
- }
-
- /**
- * This method aims to be overridden
- */
- protected void doAfterStart() {
- // nothing
- }
-}
import org.sonar.core.platform.PluginClassloaderFactory;
import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginRepository;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.core.util.DefaultHttpDownloader;
import org.sonar.core.util.UuidFactoryImpl;
import org.sonar.scanner.extension.ScannerCoreExtensionsInstaller;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.scanner.bootstrap;
-
-import org.sonar.api.Startable;
-import org.sonar.api.utils.log.Loggers;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
-import org.springframework.lang.Nullable;
-
-public class StartableBeanPostProcessor implements DestructionAwareBeanPostProcessor {
- @Override
- @Nullable
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- if (bean instanceof Startable) {
- ((Startable) bean).start();
- } else if (bean instanceof org.picocontainer.Startable) {
- ((org.picocontainer.Startable) bean).start();
- }
- return bean;
- }
-
- @Override
- public boolean requiresDestruction(Object bean) {
- return (bean instanceof Startable) || (bean instanceof org.picocontainer.Startable) || (bean instanceof AutoCloseable);
- }
-
- @Override
- public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
- try {
- if (bean instanceof Startable) {
- ((Startable) bean).stop();
- } else if (bean instanceof org.picocontainer.Startable) {
- ((org.picocontainer.Startable) bean).stop();
- } else if (bean instanceof AutoCloseable) {
- ((AutoCloseable) bean).close();
- }
- } catch (Exception e) {
- Loggers.get(StartableBeanPostProcessor.class)
- .warn("Dispose of component {} failed", bean.getClass().getCanonicalName(), e);
- }
- }
-}
@Bean("DefaultInputProject")
public DefaultInputProject provide(ProjectBuildersExecutor projectBuildersExecutor, ProjectReactorValidator validator,
- ProjectReactor projectReactor, ScannerComponentIdGenerator scannerComponentIdGenerator) {
+ ProjectReactor projectReactor, ScannerComponentIdGenerator scannerComponentIdGenerator, WorkDirectoriesInitializer workDirectoriesInit) {
// 1 Apply project builders
projectBuildersExecutor.execute(projectReactor);
// 3 Create project
DefaultInputProject project = new DefaultInputProject(projectReactor.getRoot(), scannerComponentIdGenerator.getAsInt());
+ workDirectoriesInit.execute(project);
LOG.info("Project key: {}", project.key());
LOG.info("Base dir: {}", project.getBaseDir().toAbsolutePath().toString());
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.scanner.scan;
-
-import java.util.List;
-import java.util.Optional;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.springframework.context.annotation.Bean;
-
-public class LanguagesProvider {
- @Bean("Languages")
- public Languages provide(Optional<List<Language>> languages) {
- if (languages.isEmpty()) {
- return new Languages();
- }
- return new Languages(languages.get().toArray(new Language[0]));
- }
-}
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.scan.filesystem.FileExclusions;
import org.sonar.scanner.bootstrap.ExtensionInstaller;
-import org.sonar.scanner.bootstrap.SpringComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem;
import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore;
import org.sonar.scanner.sensor.ModuleSensorContext;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.config.ScannerProperties;
import org.sonar.core.extension.CoreExtensionsInstaller;
+import org.sonar.core.language.LanguagesProvider;
import org.sonar.core.metric.ScannerMetrics;
import org.sonar.scanner.DefaultFileLinesContextFactory;
import org.sonar.scanner.ProjectInfo;
import org.sonar.scanner.bootstrap.ExtensionMatcher;
import org.sonar.scanner.bootstrap.GlobalAnalysisMode;
import org.sonar.scanner.bootstrap.PostJobExtensionDictionary;
-import org.sonar.scanner.bootstrap.SpringComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.scanner.ci.CiConfigurationProvider;
import org.sonar.scanner.ci.vendors.AppVeyor;
import org.sonar.scanner.ci.vendors.AwsCodeBuild;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
-import org.sonar.core.util.FileUtils;
+import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.core.util.FileUtils;
import org.sonar.scanner.fs.InputModuleHierarchy;
/**
- * Clean and create working directories of each module.
+ * Clean and create working directories of each module, except the root.
* Be careful that sub module work dir might be nested in parent working directory.
*/
public class WorkDirectoriesInitializer {
public void execute(InputModuleHierarchy moduleHierarchy) {
- cleanAllWorkingDirs(moduleHierarchy, moduleHierarchy.root());
- mkdirsAllWorkingDirs(moduleHierarchy, moduleHierarchy.root());
+ // dont apply to root. Root is done by InputProjectProvider
+ for (DefaultInputModule sub : moduleHierarchy.children(moduleHierarchy.root())) {
+ cleanAllWorkingDirs(moduleHierarchy, sub);
+ }
+ for (DefaultInputModule sub : moduleHierarchy.children(moduleHierarchy.root())) {
+ mkdirsAllWorkingDirs(moduleHierarchy, sub);
+ }
+ }
+
+ public void execute(DefaultInputProject project) {
+ cleanWorkingDir(project);
+ mkdirWorkingDir(project);
}
private static void cleanAllWorkingDirs(InputModuleHierarchy moduleHierarchy, DefaultInputModule module) {
for (DefaultInputModule sub : moduleHierarchy.children(module)) {
cleanAllWorkingDirs(moduleHierarchy, sub);
}
- if (Files.exists(module.getWorkDir())) {
- deleteAllRecursivelyExceptLockFile(module.getWorkDir());
+ cleanWorkingDir(module);
+ }
+
+ private static void cleanWorkingDir(AbstractProjectOrModule projectOrModule) {
+ if (Files.exists(projectOrModule.getWorkDir())) {
+ deleteAllRecursivelyExceptLockFile(projectOrModule.getWorkDir());
}
}
for (DefaultInputModule sub : moduleHierarchy.children(module)) {
mkdirsAllWorkingDirs(moduleHierarchy, sub);
}
+ mkdirWorkingDir(module);
+ }
+
+ private static void mkdirWorkingDir(AbstractProjectOrModule projectOrModule) {
try {
- Files.createDirectories(module.getWorkDir());
+ Files.createDirectories(projectOrModule.getWorkDir());
} catch (Exception e) {
- throw new IllegalStateException("Fail to create working dir: " + module.getWorkDir(), e);
+ throw new IllegalStateException("Fail to create working dir: " + projectOrModule.getWorkDir(), e);
}
}
import java.util.Collection;
import java.util.stream.Collectors;
import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ExtensionContainer;
import org.sonar.scanner.bootstrap.AbstractExtensionDictionary;
-import org.sonar.scanner.bootstrap.SpringComponentContainer;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.scan.filesystem.MutableFileSystem;
private final MutableFileSystem fileSystem;
private final BranchConfiguration branchConfiguration;
- public ModuleSensorExtensionDictionary(SpringComponentContainer componentContainer, ModuleSensorContext sensorContext, ModuleSensorOptimizer sensorOptimizer,
+ public ModuleSensorExtensionDictionary(ExtensionContainer componentContainer, ModuleSensorContext sensorContext, ModuleSensorOptimizer sensorOptimizer,
MutableFileSystem fileSystem, BranchConfiguration branchConfiguration) {
super(componentContainer);
this.sensorContext = sensorContext;
import java.util.stream.Collectors;
import org.sonar.api.scanner.sensor.ProjectSensor;
import org.sonar.scanner.bootstrap.AbstractExtensionDictionary;
-import org.sonar.scanner.bootstrap.SpringComponentContainer;
+import org.sonar.core.platform.SpringComponentContainer;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.scan.filesystem.MutableFileSystem;
<level value="INFO"/>
</logger>
- <logger name="org.sonar.scanner.bootstrap.PriorityBeanFactory">
+ <logger name="org.sonar.core.platform.PriorityBeanFactory">
<level value="INFO"/>
</logger>
package org.sonar.scanner.bootstrap;
import java.util.Arrays;
+
import org.apache.commons.lang.ClassUtils;
import org.junit.Test;
import org.sonar.api.Plugin;
import org.sonar.api.SonarRuntime;
import org.sonar.api.batch.ScannerSide;
import org.sonar.api.config.internal.MapSettings;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import org.sonar.core.platform.PluginInfo;
import static org.assertj.core.api.Assertions.assertThat;
public class ExtensionInstallerTest {
- private MapSettings settings = new MapSettings();
- private ScannerPluginRepository pluginRepository = mock(ScannerPluginRepository.class);
+ private final MapSettings settings = new MapSettings();
+ private final ScannerPluginRepository pluginRepository = mock(ScannerPluginRepository.class);
private static Plugin newPluginInstance(final Object... extensions) {
return desc -> desc.addExtensions(Arrays.asList(extensions));
when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo")));
when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(Foo.class, Bar.class));
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
ExtensionInstaller installer = new ExtensionInstaller(mock(SonarRuntime.class), pluginRepository, settings.asConfig());
installer.install(container, new FooMatcher());
- assertThat(container.getComponentByType(Foo.class)).isNotNull();
- assertThat(container.getComponentByType(Bar.class)).isNull();
+ assertThat(container.getAddedObjects())
+ .contains(Foo.class)
+ .doesNotContain(Bar.class);
}
private static class FooMatcher implements ExtensionMatcher {
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.scanner.bootstrap;
-
-import org.junit.Test;
-import org.springframework.beans.factory.support.DefaultListableBeanFactory;
-import org.springframework.beans.factory.support.RootBeanDefinition;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class LazyBeanFactoryPostProcessorTest {
- private final LazyBeanFactoryPostProcessor postProcessor = new LazyBeanFactoryPostProcessor();
-
- @Test
- public void sets_all_beans_lazy() {
- DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
- beanFactory.registerBeanDefinition("bean1", new RootBeanDefinition());
- assertThat(beanFactory.getBeanDefinition("bean1").isLazyInit()).isFalse();
-
- postProcessor.postProcessBeanFactory(beanFactory);
- assertThat(beanFactory.getBeanDefinition("bean1").isLazyInit()).isTrue();
- }
-
-}
*/
package org.sonar.scanner.bootstrap;
-import com.google.common.collect.Lists;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
import org.junit.Before;
import org.junit.Test;
-import org.picocontainer.behaviors.FieldDecorated;
import org.sonar.api.batch.DependedUpon;
import org.sonar.api.batch.DependsUpon;
import org.sonar.api.batch.Phase;
import org.sonar.api.batch.ScannerSide;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
-import org.sonar.scanner.scan.SpringModuleScanContainer;
+import org.sonar.core.platform.ExtensionContainer;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.scan.filesystem.MutableFileSystem;
import org.sonar.scanner.sensor.ModuleSensorContext;
import org.sonar.scanner.sensor.ModuleSensorOptimizer;
import org.sonar.scanner.sensor.ModuleSensorWrapper;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
when(sensorOptimizer.shouldExecute(any(DefaultSensorDescriptor.class))).thenReturn(true);
}
- private ModuleSensorExtensionDictionary newSelector(Object... extensions) {
- DefaultInputModule inputModule = mock(DefaultInputModule.class);
- when(inputModule.definition()).thenReturn(mock(ProjectDefinition.class));
-
- SpringComponentContainer parent = new SpringComponentContainer();
- parent.context.refresh();
-
- SpringComponentContainer iocContainer = new SpringModuleScanContainer(parent, inputModule);
- iocContainer.add(Arrays.asList(extensions));
- iocContainer.context.refresh();
-
+ private ModuleSensorExtensionDictionary newSelector(Class type, Object... instances) {
+ ExtensionContainer iocContainer = mock(ExtensionContainer.class);
+ when(iocContainer.getComponentsByType(type)).thenReturn(Arrays.asList(instances));
return new ModuleSensorExtensionDictionary(iocContainer, mock(ModuleSensorContext.class), sensorOptimizer, fileSystem, branchConfiguration);
}
final Sensor sensor1 = new FakeSensor();
final Sensor sensor2 = new FakeSensor();
- ModuleSensorExtensionDictionary selector = newSelector(sensor1, sensor2);
+ ModuleSensorExtensionDictionary selector = newSelector(Sensor.class, sensor1, sensor2);
Collection<Sensor> sensors = selector.select(Sensor.class, true, extension -> extension.equals(sensor1));
assertThat(sensors).contains(sensor1);
assertEquals(1, sensors.size());
public void testGetFilteredExtensions() {
Sensor sensor1 = new FakeSensor();
Sensor sensor2 = new FakeSensor();
- FieldDecorated.Decorator decorator = mock(FieldDecorated.Decorator.class);
- ModuleSensorExtensionDictionary selector = newSelector(sensor1, sensor2, decorator);
+ ModuleSensorExtensionDictionary selector = newSelector(Sensor.class, sensor1, sensor2);
Collection<Sensor> sensors = selector.select(Sensor.class, false, null);
assertThat(sensors).containsOnly(sensor1, sensor2);
Sensor b = new FakeSensor();
Sensor c = new FakeSensor();
- SpringComponentContainer grandParent = new SpringComponentContainer();
- grandParent.add(a);
- grandParent.context.refresh();
+ ExtensionContainer grandParent = mock(ExtensionContainer.class);
+ when(grandParent.getComponentsByType(Sensor.class)).thenReturn(List.of(a));
- SpringComponentContainer parent = grandParent.createChild();
- parent.add(b);
- parent.context.refresh();
+ ExtensionContainer parent = mock(ExtensionContainer.class);
+ when(parent.getComponentsByType(Sensor.class)).thenReturn(List.of(b));
+ when(parent.getParent()).thenReturn(grandParent);
- SpringComponentContainer child = parent.createChild();
- child.add(c);
- child.context.refresh();
+ ExtensionContainer child = mock(ExtensionContainer.class);
+ when(child.getComponentsByType(Sensor.class)).thenReturn(List.of(c));
+ when(child.getParent()).thenReturn(parent);
ModuleSensorExtensionDictionary dictionnary = new ModuleSensorExtensionDictionary(child, mock(ModuleSensorContext.class), mock(ModuleSensorOptimizer.class),
fileSystem, branchConfiguration);
Object b = new MethodDependentOf(a);
Object c = new MethodDependentOf(b);
- ModuleSensorExtensionDictionary selector = newSelector(b, c, a);
- List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ ModuleSensorExtensionDictionary selector = newSelector(Marker.class, b, c, a);
+ List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(3);
assertThat(extensions.get(0)).isEqualTo(a);
Object a = new GeneratesSomething("foo");
Object b = new MethodDependentOf("foo");
- ModuleSensorExtensionDictionary selector = newSelector(a, b);
- List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ ModuleSensorExtensionDictionary selector = newSelector(Marker.class, a, b);
+ List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions.size()).isEqualTo(2);
assertThat(extensions.get(0)).isEqualTo(a);
assertThat(extensions.get(1)).isEqualTo(b);
// different initial order
- selector = newSelector(b, a);
- extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ selector = newSelector(Marker.class, b, a);
+ extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(2);
assertThat(extensions.get(0)).isEqualTo(a);
Object a = new GeneratesSomething("foo");
Object b = new MethodDependentOf(Arrays.asList("foo"));
- ModuleSensorExtensionDictionary selector = newSelector(a, b);
- List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ ModuleSensorExtensionDictionary selector = newSelector(Marker.class, a, b);
+ List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(2);
assertThat(extensions.get(0)).isEqualTo(a);
assertThat(extensions.get(1)).isEqualTo(b);
// different initial order
- selector = newSelector(b, a);
- extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ selector = newSelector(Marker.class, b, a);
+ extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(2);
assertThat(extensions.get(0)).isEqualTo(a);
Object a = new GeneratesSomething("foo");
Object b = new MethodDependentOf(new String[] {"foo"});
- ModuleSensorExtensionDictionary selector = newSelector(a, b);
- List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ ModuleSensorExtensionDictionary selector = newSelector(Marker.class, a, b);
+ List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(2);
assertThat(extensions.get(0)).isEqualTo(a);
assertThat(extensions.get(1)).isEqualTo(b);
// different initial order
- selector = newSelector(b, a);
- extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ selector = newSelector(Marker.class, b, a);
+ extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(2);
assertThat(extensions.get(0)).isEqualTo(a);
Object a = new ClassDependedUpon();
Object b = new ClassDependsUpon();
- ModuleSensorExtensionDictionary selector = newSelector(a, b);
- List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ ModuleSensorExtensionDictionary selector = newSelector(Marker.class, a, b);
+ List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(2);
assertThat(extensions.get(0)).isEqualTo(a);
assertThat(extensions.get(1)).isEqualTo(b);
// different initial order
- selector = newSelector(b, a);
- extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ selector = newSelector(Marker.class, b, a);
+ extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(2);
assertThat(extensions.get(0)).isEqualTo(a);
Object b = new InterfaceDependsUpon() {
};
- ModuleSensorExtensionDictionary selector = newSelector(a, b);
- List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ ModuleSensorExtensionDictionary selector = newSelector(Marker.class, a, b);
+ List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(2);
assertThat(extensions.get(0)).isEqualTo(a);
assertThat(extensions.get(1)).isEqualTo(b);
// different initial order
- selector = newSelector(b, a);
- extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ selector = newSelector(Marker.class, b, a);
+ extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(2);
assertThat(extensions.get(0)).isEqualTo(a);
Object a = new SubClass("foo");
Object b = new MethodDependentOf("foo");
- ModuleSensorExtensionDictionary selector = newSelector(b, a);
- List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ ModuleSensorExtensionDictionary selector = newSelector(Marker.class, b, a);
+ List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(2);
assertThat(extensions.get(0)).isEqualTo(a);
assertThat(extensions.get(1)).isEqualTo(b);
// change initial order
- selector = newSelector(a, b);
- extensions = Lists.newArrayList(selector.select(Marker.class, true, null));
+ selector = newSelector(Marker.class, a, b);
+ extensions = new ArrayList<>(selector.select(Marker.class, true, null));
assertThat(extensions).hasSize(2);
assertThat(extensions.get(0)).isEqualTo(a);
@Test(expected = IllegalStateException.class)
public void annotatedMethodsCanNotBePrivate() {
- ModuleSensorExtensionDictionary selector = newSelector();
+ ModuleSensorExtensionDictionary selector = new ModuleSensorExtensionDictionary(mock(ExtensionContainer.class), mock(ModuleSensorContext.class),
+ sensorOptimizer, fileSystem, branchConfiguration);
Object wrong = new Object() {
@DependsUpon
private Object foo() {
NormalSensor normal = new NormalSensor();
PostSensor post = new PostSensor();
- ModuleSensorExtensionDictionary selector = newSelector(normal, post, pre);
+ ModuleSensorExtensionDictionary selector = newSelector(Sensor.class, normal, post, pre);
assertThat(selector.selectSensors(false)).extracting("wrappedSensor").containsExactly(pre, normal, post);
}
NormalSensor normal = new NormalSensor();
PostSensorSubclass post = new PostSensorSubclass();
- ModuleSensorExtensionDictionary selector = newSelector(normal, post, pre);
- List extensions = Lists.newArrayList(selector.select(Sensor.class, true, null));
+ ModuleSensorExtensionDictionary selector = newSelector(Sensor.class, normal, post, pre);
+ List extensions = new ArrayList<>(selector.select(Sensor.class, true, null));
assertThat(extensions).containsExactly(pre, normal, post);
}
public void selectSensors() {
FakeSensor nonGlobalSensor = new FakeSensor();
FakeGlobalSensor globalSensor = new FakeGlobalSensor();
- ModuleSensorExtensionDictionary selector = newSelector(nonGlobalSensor, globalSensor);
+ ModuleSensorExtensionDictionary selector = newSelector(Sensor.class, nonGlobalSensor, globalSensor);
// verify non-global sensor
Collection<ModuleSensorWrapper> extensions = selector.selectSensors(false);
*/
package org.sonar.scanner.bootstrap;
+import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.Phase;
import org.sonar.api.batch.postjob.PostJobContext;
import org.sonar.api.batch.postjob.PostJobDescriptor;
import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ExtensionContainer;
import org.sonar.scanner.postjob.PostJobOptimizer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
public class PostJobExtensionDictionaryTest {
- private PostJobOptimizer postJobOptimizer = mock(PostJobOptimizer.class);
+ private final PostJobOptimizer postJobOptimizer = mock(PostJobOptimizer.class);
@Before
public void setUp() {
when(postJobOptimizer.shouldExecute(any(DefaultPostJobDescriptor.class))).thenReturn(true);
}
- private PostJobExtensionDictionary newSelector(Object... extensions) {
- ComponentContainer iocContainer = new ComponentContainer();
- for (Object extension : extensions) {
- iocContainer.addSingleton(extension);
- }
- return new PostJobExtensionDictionary(iocContainer, postJobOptimizer, mock(PostJobContext.class));
- }
-
@Test
public void dependsUponPhaseForPostJob() {
PrePostJob pre = new PrePostJob();
NormalPostJob normal = new NormalPostJob();
- PostJobExtensionDictionary selector = newSelector(normal, pre);
- assertThat(selector.selectPostJobs()).extracting("wrappedPostJob").containsExactly(pre, normal);
- }
-
- interface Marker {
-
- }
-
- @Phase(name = Phase.Name.POST) static
- class PostSensor implements Sensor {
-
- @Override
- public void describe(SensorDescriptor descriptor) {
- }
-
- @Override
- public void execute(SensorContext context) {
- }
-
- }
-
- class PostSensorSubclass extends PostSensor {
+ ExtensionContainer iocContainer = mock(ExtensionContainer.class);
+ when(iocContainer.getComponentsByType(PostJob.class)).thenReturn(List.of(pre, normal));
+ PostJobExtensionDictionary selector = new PostJobExtensionDictionary(iocContainer, postJobOptimizer, mock(PostJobContext.class));
+ assertThat(selector.selectPostJobs()).extracting("wrappedPostJob").containsExactly(pre, normal);
}
static class NormalPostJob implements PostJob {
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.scanner.bootstrap;
-
-import javax.annotation.Priority;
-import org.junit.Before;
-import org.junit.Test;
-import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
-import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
-import org.springframework.beans.factory.support.DefaultListableBeanFactory;
-import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.core.annotation.AnnotationAwareOrderComparator;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-public class PriorityBeanFactoryTest {
- private final DefaultListableBeanFactory parentBeanFactory = new PriorityBeanFactory();
- private final DefaultListableBeanFactory beanFactory = new PriorityBeanFactory();
-
- @Before
- public void setUp() {
- // needed to support autowiring with @Inject
- beanFactory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
- //needed to read @Priority
- beanFactory.setDependencyComparator(new AnnotationAwareOrderComparator());
- beanFactory.setParentBeanFactory(parentBeanFactory);
- }
-
- @Test
- public void give_priority_to_child_container() {
- parentBeanFactory.registerBeanDefinition("A1", new RootBeanDefinition(A1.class));
-
- beanFactory.registerBeanDefinition("A2", new RootBeanDefinition(A2.class));
- beanFactory.registerBeanDefinition("B", new RootBeanDefinition(B.class));
-
- assertThat(beanFactory.getBean(B.class).dep.getClass()).isEqualTo(A2.class);
- }
-
- @Test
- public void follow_priority_annotations() {
- parentBeanFactory.registerBeanDefinition("A3", new RootBeanDefinition(A3.class));
-
- beanFactory.registerBeanDefinition("A1", new RootBeanDefinition(A1.class));
- beanFactory.registerBeanDefinition("A2", new RootBeanDefinition(A2.class));
- beanFactory.registerBeanDefinition("B", new RootBeanDefinition(B.class));
-
- assertThat(beanFactory.getBean(B.class).dep.getClass()).isEqualTo(A3.class);
- }
-
- @Test
- public void throw_NoUniqueBeanDefinitionException_if_cant_find_single_bean_with_higher_priority() {
- beanFactory.registerBeanDefinition("A1", new RootBeanDefinition(A1.class));
- beanFactory.registerBeanDefinition("A2", new RootBeanDefinition(A2.class));
- beanFactory.registerBeanDefinition("B", new RootBeanDefinition(B.class));
-
- assertThatThrownBy(() -> beanFactory.getBean(B.class))
- .hasRootCauseInstanceOf(NoUniqueBeanDefinitionException.class);
- }
-
- private static class B {
- private final A dep;
-
- public B(A dep) {
- this.dep = dep;
- }
- }
-
- private interface A {
-
- }
-
- private static class A1 implements A {
-
- }
-
- private static class A2 implements A {
-
- }
-
- @Priority(1)
- private static class A3 implements A {
-
- }
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.scanner.bootstrap;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import org.junit.Test;
-import org.sonar.api.Startable;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertThrows;
-
-public class SpringComponentContainerTest {
-
- @Test
- public void should_stop_after_failing() {
- ApiStartable startStop = new ApiStartable();
- SpringComponentContainer container = new SpringComponentContainer() {
- @Override
- public void doBeforeStart() {
- add(startStop);
- }
-
- @Override
- public void doAfterStart() {
- getComponentByType(ApiStartable.class);
- throw new IllegalStateException("doBeforeStart");
- }
- };
-
- assertThrows("doBeforeStart", IllegalStateException.class, container::execute);
- assertThat(startStop.start).isTrue();
- assertThat(startStop.stop).isTrue();
- }
-
- @Test
- public void register_instance_with_toString() {
- SpringComponentContainer container = new SimpleContainer(new ToString("a"), new ToString("b"));
- container.startComponents();
- assertThat(container.context.getBeanDefinitionNames())
- .contains(
- this.getClass().getClassLoader() + "-org.sonar.scanner.bootstrap.SpringComponentContainerTest.ToString-a",
- this.getClass().getClassLoader() + "-org.sonar.scanner.bootstrap.SpringComponentContainerTest.ToString-b");
- assertThat(container.getComponentsByType(ToString.class)).hasSize(2);
- }
-
- @Test
- public void register_class_with_classloader_and_fqcn() {
- SpringComponentContainer container = new SimpleContainer(A.class, B.class);
- container.startComponents();
- assertThat(container.context.getBeanDefinitionNames())
- .contains(
- this.getClass().getClassLoader() + "-org.sonar.scanner.bootstrap.SpringComponentContainerTest.A",
- this.getClass().getClassLoader() + "-org.sonar.scanner.bootstrap.SpringComponentContainerTest.B");
- assertThat(container.getComponentByType(A.class)).isNotNull();
- assertThat(container.getComponentByType(B.class)).isNotNull();
- }
-
- @Test
- public void should_throw_start_exception_if_stop_also_throws_exception() {
- ErrorStopClass errorStopClass = new ErrorStopClass();
- SpringComponentContainer container = new SpringComponentContainer() {
- @Override
- public void doBeforeStart() {
- add(errorStopClass);
- }
-
- @Override
- public void doAfterStart() {
- getComponentByType(ErrorStopClass.class);
- throw new IllegalStateException("doBeforeStart");
- }
- };
- assertThrows("doBeforeStart", IllegalStateException.class, container::execute);
- assertThat(errorStopClass.stopped).isTrue();
- }
-
- @Test
- public void should_support_extensions_without_annotations() {
- SpringComponentContainer container = new SimpleContainer(A.class, B.class);
- container.addExtension("", ExtensionWithMultipleConstructorsAndNoAnnotations.class);
- container.startComponents();
- assertThat(container.getComponentByType(ExtensionWithMultipleConstructorsAndNoAnnotations.class).gotBothArgs).isTrue();
- }
-
- @Test
- public void support_start_stop_callbacks() {
- JsrLifecycleCallbacks jsr = new JsrLifecycleCallbacks();
- ApiStartable api = new ApiStartable();
- PicoStartable pico = new PicoStartable();
-
- SpringComponentContainer container = new SimpleContainer(jsr, api, pico) {
- @Override
- public void doAfterStart() {
- // force lazy instantiation
- getComponentByType(JsrLifecycleCallbacks.class);
- getComponentByType(ApiStartable.class);
- getComponentByType(PicoStartable.class);
- }
- };
- container.execute();
-
- assertThat(jsr.postConstruct).isTrue();
- assertThat(jsr.preDestroy).isTrue();
- assertThat(api.start).isTrue();
- assertThat(api.stop).isTrue();
- assertThat(pico.start).isTrue();
- assertThat(pico.stop).isTrue();
- }
-
- private static class JsrLifecycleCallbacks {
- private boolean postConstruct = false;
- private boolean preDestroy = false;
-
- @PostConstruct
- public void postConstruct() {
- postConstruct = true;
- }
-
- @PreDestroy
- public void preDestroy() {
- preDestroy = true;
- }
- }
-
- private static class ApiStartable implements Startable {
- private boolean start = false;
- private boolean stop = false;
-
- public void start() {
- start = true;
- }
-
- public void stop() {
- stop = true;
- }
- }
-
- private static class PicoStartable implements org.picocontainer.Startable {
- private boolean start = false;
- private boolean stop = false;
-
- public void start() {
- start = true;
- }
-
- public void stop() {
- stop = true;
- }
- }
-
- private static class ToString {
- private final String toString;
-
- public ToString(String toString) {
- this.toString = toString;
- }
-
- @Override
- public String toString() {
- return toString;
- }
- }
-
- private static class A {
- }
-
- private static class B {
- }
-
- private static class ExtensionWithMultipleConstructorsAndNoAnnotations {
- private boolean gotBothArgs = false;
- public ExtensionWithMultipleConstructorsAndNoAnnotations(A a) {
- }
-
- public ExtensionWithMultipleConstructorsAndNoAnnotations(A a, B b) {
- gotBothArgs = true;
- }
- }
-
- private static class ErrorStopClass implements Startable {
- private boolean stopped = false;
-
- @Override
- public void start() {
- }
-
- @Override
- public void stop() {
- stopped = true;
- throw new IllegalStateException("stop");
- }
- }
-
- private static class SimpleContainer extends SpringComponentContainer {
- public SimpleContainer(Object... objects) {
- add(objects);
- }
- }
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.scanner.bootstrap;
-
-import org.junit.Test;
-import org.picocontainer.Startable;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-public class StartableBeanPostProcessorTest {
- private final StartableBeanPostProcessor underTest = new StartableBeanPostProcessor();
-
- @Test
- public void starts_pico_startable() {
- Startable startable = mock(Startable.class);
- underTest.postProcessBeforeInitialization(startable, "startable");
- verify(startable).start();
- verifyNoMoreInteractions(startable);
- }
-
- @Test
- public void starts_api_startable() {
- org.sonar.api.Startable startable = mock(org.sonar.api.Startable.class);
- underTest.postProcessBeforeInitialization(startable, "startable");
- verify(startable).start();
- verifyNoMoreInteractions(startable);
- }
-
- @Test
- public void stops_pico_startable() {
- Startable startable = mock(Startable.class);
- underTest.postProcessBeforeDestruction(startable, "startable");
- verify(startable).stop();
- verifyNoMoreInteractions(startable);
- }
-
- @Test
- public void stops_api_startable() {
- org.sonar.api.Startable startable = mock(org.sonar.api.Startable.class);
- underTest.postProcessBeforeDestruction(startable, "startable");
- verify(startable).stop();
- verifyNoMoreInteractions(startable);
- }
-
-}
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.stream.Stream;
+
import org.junit.Test;
import org.sonar.api.SonarRuntime;
import org.sonar.api.scanner.ScannerSide;
import org.sonar.api.server.ServerSide;
import org.sonar.core.extension.CoreExtension;
import org.sonar.core.extension.CoreExtensionRepository;
-import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.ListContainer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter;
public class ScannerCoreExtensionsInstallerTest {
- private SonarRuntime sonarRuntime = mock(SonarRuntime.class);
- private CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class);
-
- private ScannerCoreExtensionsInstaller underTest = new ScannerCoreExtensionsInstaller(sonarRuntime, coreExtensionRepository);
+ private final SonarRuntime sonarRuntime = mock(SonarRuntime.class);
+ private final CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class);
+ private final ScannerCoreExtensionsInstaller underTest = new ScannerCoreExtensionsInstaller(sonarRuntime, coreExtensionRepository);
@Test
public void install_only_adds_ScannerSide_annotated_extension_to_container() {
NoAnnotationClass.class, OtherAnnotationClass.class, MultipleAnnotationClass.class);
}
}));
- ComponentContainer container = new ComponentContainer();
+ ListContainer container = new ListContainer();
underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
- assertThat(container.getPicoContainer().getComponentAdapters())
- .hasSize(ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
- assertThat(container.getComponentByType(ScannerClass.class)).isNotNull();
- assertThat(container.getComponentByType(MultipleAnnotationClass.class)).isNotNull();
+ assertThat(container.getAddedObjects())
+ .hasSize(2)
+ .contains(ScannerClass.class, MultipleAnnotationClass.class);
}
@ComputeEngineSide
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.scanner.mediumtest.ScannerMediumTester;
-import org.springframework.beans.factory.UnsatisfiedDependencyException;
+import org.springframework.beans.factory.BeanCreationException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
assertThatThrownBy(() -> tester
.newAnalysis(new File(projectDir, "sonar-project.properties"))
.execute())
- .isInstanceOf(UnsatisfiedDependencyException.class)
+ .isInstanceOf(BeanCreationException.class)
.hasRootCauseMessage("No language plugins are installed.");
}
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.scanner.fs.InputModuleHierarchy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
public class WorkDirectoriesInitializerTest {
- private WorkDirectoriesInitializer initializer;
+ private final WorkDirectoriesInitializer initializer = new WorkDirectoriesInitializer();
+ private final InputModuleHierarchy hierarchy = mock(InputModuleHierarchy.class);
+ private final DefaultInputProject project = mock(DefaultInputProject.class);
+ private final DefaultInputModule root = mock(DefaultInputModule.class);
+
@Rule
public TemporaryFolder temp = new TemporaryFolder();
private File rootWorkDir;
private File lock;
- private InputModuleHierarchy hierarchy;
- private DefaultInputModule root;
@Before
public void setUp() throws IOException {
rootWorkDir = temp.newFolder();
- // create files to clean
- new File(rootWorkDir, "foo.txt").createNewFile();
- File newFolder = new File(rootWorkDir, "foo");
+ when(hierarchy.root()).thenReturn(root);
+ createFilesToClean(rootWorkDir);
+ when(root.getWorkDir()).thenReturn(rootWorkDir.toPath());
+ when(project.getWorkDir()).thenReturn(rootWorkDir.toPath());
+ }
+
+ private void createFilesToClean(File dir) throws IOException {
+ new File(dir, "foo.txt").createNewFile();
+ File newFolder = new File(dir, "foo");
newFolder.mkdir();
File fileInFolder = new File(newFolder, "test");
fileInFolder.createNewFile();
- lock = new File(rootWorkDir, DirectoryLock.LOCK_FILE_NAME);
+ lock = new File(dir, DirectoryLock.LOCK_FILE_NAME);
lock.createNewFile();
-
- hierarchy = mock(InputModuleHierarchy.class);
- root = mock(DefaultInputModule.class);
- when(hierarchy.root()).thenReturn(root);
- when(root.getWorkDir()).thenReturn(rootWorkDir.toPath());
-
- assertThat(rootWorkDir.list().length).isGreaterThan(1);
- initializer = new WorkDirectoriesInitializer();
+ assertThat(dir.list()).hasSizeGreaterThan(1);
}
@Test
- public void testNonExisting() {
+ public void execute_doesnt_fail_if_nothing_to_clean() {
temp.delete();
initializer.execute(hierarchy);
}
@Test
- public void testClean() {
- initializer.execute(hierarchy);
+ public void execute_should_clean_root() {
+ initializer.execute(project);
assertThat(rootWorkDir).exists();
assertThat(lock).exists();
}
@Test
- public void cleaningRootModuleShouldNotDeleteChildrenWorkDir() throws IOException {
+ public void execute_on_hierarchy_should_clean_submodules() throws IOException {
DefaultInputModule moduleA = mock(DefaultInputModule.class);
+ DefaultInputModule moduleB = mock(DefaultInputModule.class);
+
when(hierarchy.children(root)).thenReturn(Arrays.asList(moduleA));
+ when(hierarchy.children(moduleA)).thenReturn(Arrays.asList(moduleB));
+
File moduleAWorkdir = new File(rootWorkDir, "moduleA");
+ File moduleBWorkdir = new File(moduleAWorkdir, "moduleB");
+
when(moduleA.getWorkDir()).thenReturn(moduleAWorkdir.toPath());
+ when(moduleB.getWorkDir()).thenReturn(moduleBWorkdir.toPath());
+
moduleAWorkdir.mkdir();
+ moduleBWorkdir.mkdir();
+
new File(moduleAWorkdir, "fooA.txt").createNewFile();
+ new File(moduleBWorkdir, "fooB.txt").createNewFile();
+ initializer.execute(project);
initializer.execute(hierarchy);
assertThat(rootWorkDir).exists();
assertThat(lock).exists();
assertThat(rootWorkDir.list()).containsOnly(DirectoryLock.LOCK_FILE_NAME, "moduleA");
assertThat(moduleAWorkdir).exists();
+ assertThat(moduleBWorkdir).exists();
+ assertThat(moduleAWorkdir.list()).containsOnly("moduleB");
+ assertThat(moduleBWorkdir).isEmptyDirectory();
}
}