瀏覽代碼

SONAR-15966 Use Spring instead of Pico as dependency injection framework in the scanner-engine

Co-authored-by: Zipeng WU <zipeng.wu@sonarsource.com>
tags/9.4.0.54424
Duarte Meneses 2 年之前
父節點
當前提交
a53007e824
共有 100 個檔案被更改,包括 1531 行新增627 行删除
  1. 4
    0
      build.gradle
  2. 4
    4
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/AbstractComputationSteps.java
  3. 2
    1
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/AuditPurgeTaskProcessor.java
  4. 2
    1
      server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/IssueSyncTaskProcessor.java
  5. 2
    2
      server/sonar-ce-task/src/main/java/org/sonar/ce/task/container/TaskContainer.java
  6. 2
    2
      server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/engine/MigrationContainer.java
  7. 2
    0
      sonar-core/build.gradle
  8. 16
    18
      sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsInstaller.java
  9. 2
    0
      sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsLoader.java
  10. 3
    0
      sonar-core/src/main/java/org/sonar/core/metric/ScannerMetrics.java
  11. 9
    3
      sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java
  12. 12
    4
      sonar-core/src/main/java/org/sonar/core/platform/ComponentKeys.java
  13. 34
    0
      sonar-core/src/main/java/org/sonar/core/platform/Container.java
  14. 1
    13
      sonar-core/src/main/java/org/sonar/core/platform/ContainerPopulator.java
  15. 36
    0
      sonar-core/src/main/java/org/sonar/core/platform/ExtensionContainer.java
  16. 2
    0
      sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java
  17. 8
    1
      sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/DefaultTempFolder.java
  18. 4
    4
      sonar-plugin-api/src/test/java/org/sonar/api/resources/LanguagesTest.java
  19. 3
    0
      sonar-scanner-engine/build.gradle
  20. 2
    2
      sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/Batch.java
  21. 2
    2
      sonar-scanner-engine/src/main/java/org/sonar/scanner/ProjectInfo.java
  22. 11
    44
      sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/AnalysisTempFolderProvider.java
  23. 5
    5
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/AbstractExtensionDictionary.java
  24. 62
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ClassDerivedBeanDefinition.java
  25. 3
    4
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ExtensionInstaller.java
  26. 1
    3
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalConfiguration.java
  27. 8
    15
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalConfigurationProvider.java
  28. 6
    11
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalServerSettingsProvider.java
  29. 7
    23
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalTempFolderProvider.java
  30. 35
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/LazyBeanFactoryPostProcessor.java
  31. 1
    1
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginFiles.java
  32. 3
    3
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionary.java
  33. 123
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PriorityBeanFactory.java
  34. 1
    1
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginRepository.java
  35. 23
    29
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java
  36. 231
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringComponentContainer.java
  37. 22
    27
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringGlobalContainer.java
  38. 60
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/StartableBeanPostProcessor.java
  39. 3
    2
      sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationProvider.java
  40. 3
    2
      sonar-scanner-engine/src/main/java/org/sonar/scanner/cpd/CpdExecutor.java
  41. 3
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/IssueFilters.java
  42. 2
    2
      sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisObserver.java
  43. 4
    8
      sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisObservers.java
  44. 3
    3
      sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java
  45. 2
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/FakePluginInstaller.java
  46. 1
    1
      sonar-scanner-engine/src/main/java/org/sonar/scanner/qualitygate/QualityGateCheck.java
  47. 1
    2
      sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java
  48. 4
    4
      sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java
  49. 6
    8
      sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/MetricsRepositoryProvider.java
  50. 6
    9
      sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfilesProvider.java
  51. 1
    1
      sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/DefaultLanguagesRepository.java
  52. 3
    1
      sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/settings/DefaultGlobalSettingsLoader.java
  53. 7
    9
      sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesProvider.java
  54. 4
    12
      sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RulesProvider.java
  55. 16
    17
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputModuleHierarchyProvider.java
  56. 14
    18
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputProjectProvider.java
  57. 36
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguagesProvider.java
  58. 1
    3
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleConfiguration.java
  59. 9
    15
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleConfigurationProvider.java
  60. 1
    1
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java
  61. 2
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableModuleSettings.java
  62. 4
    8
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableProjectReactorProvider.java
  63. 3
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableProjectSettings.java
  64. 3
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectBuildersExecutor.java
  65. 1
    3
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectConfiguration.java
  66. 10
    15
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectConfigurationProvider.java
  67. 1
    1
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectLock.java
  68. 3
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorValidator.java
  69. 8
    12
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectServerSettingsProvider.java
  70. 6
    5
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringModuleScanContainer.java
  71. 17
    24
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java
  72. 7
    14
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/WorkDirectoriesInitializer.java
  73. 11
    14
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/BranchConfigurationProvider.java
  74. 7
    13
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/ProjectBranchesProvider.java
  75. 7
    12
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/ProjectPullRequestsProvider.java
  76. 5
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultModuleFileSystem.java
  77. 5
    0
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultProjectFileSystem.java
  78. 0
    8
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java
  79. 6
    10
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFilesProvider.java
  80. 3
    6
      sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java
  81. 2
    2
      sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorContext.java
  82. 2
    1
      sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorExtensionDictionary.java
  83. 2
    2
      sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorExtensionDictionary.java
  84. 9
    3
      sonar-scanner-engine/src/main/resources/org/sonar/batch/bootstrapper/logback.xml
  85. 0
    4
      sonar-scanner-engine/src/main/resources/org/sonar/batch/logback.xml
  86. 0
    85
      sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalContainerTest.java
  87. 41
    0
      sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/LazyBeanFactoryPostProcessorTest.java
  88. 26
    14
      sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ModuleSensorExtensionDictionaryTest.java
  89. 103
    0
      sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PriorityBeanFactoryTest.java
  90. 0
    10
      sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java
  91. 213
    0
      sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringComponentContainerTest.java
  92. 34
    0
      sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringGlobalContainerTest.java
  93. 64
    0
      sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/StartableBeanPostProcessorTest.java
  94. 19
    2
      sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java
  95. 3
    2
      sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/NoLanguagesPluginsMediumTest.java
  96. 8
    6
      sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/issues/IssuesMediumTest.java
  97. 5
    3
      sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/log/ExceptionHandlingMediumTest.java
  98. 5
    5
      sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java
  99. 2
    2
      sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/SpringProjectScanContainerTest.java
  100. 0
    0
      sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java

+ 4
- 0
build.gradle 查看文件

@@ -350,6 +350,7 @@ subprojects {
dependency 'io.netty:netty-all:4.1.70.Final'
dependency 'com.sun.mail:javax.mail:1.5.6'
dependency 'javax.annotation:javax.annotation-api:1.3.2'
dependency 'javax.inject:javax.inject:1'
dependency 'javax.servlet:javax.servlet-api:3.1.0'
dependency 'javax.xml.bind:jaxb-api:2.3.0'
dependency 'junit:junit:4.13.2'
@@ -417,6 +418,9 @@ subprojects {
dependency 'org.simpleframework:simple:4.1.21'
dependency 'org.sonarsource.orchestrator:sonar-orchestrator:3.36.0.63'
dependency 'org.sonarsource.update-center:sonar-update-center-common:1.23.0.723'
dependency('org.springframework:spring-context:5.3.14') {
exclude 'commons-logging:commons-logging'
}
dependency 'org.subethamail:subethasmtp:3.1.7'
dependency 'org.yaml:snakeyaml:1.26'
dependency 'xml-apis:xml-apis:1.4.01'

+ 4
- 4
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/AbstractComputationSteps.java 查看文件

@@ -22,16 +22,16 @@ package org.sonar.ce.task.projectanalysis.step;
import com.google.common.collect.Iterables;
import org.sonar.ce.task.step.ComputationStep;
import org.sonar.ce.task.step.ComputationSteps;
import org.sonar.core.platform.ContainerPopulator;
import org.sonar.core.platform.Container;

/**
* Abstract implementation of {@link ComputationStep} which provides the implementation of {@link ComputationSteps#instances()}
* based on a {@link org.sonar.core.platform.ContainerPopulator.Container}.
* based on a {@link org.sonar.core.platform.Container}.
*/
public abstract class AbstractComputationSteps implements ComputationSteps {
private final ContainerPopulator.Container container;
private final Container container;

protected AbstractComputationSteps(ContainerPopulator.Container container) {
protected AbstractComputationSteps(Container container) {
this.container = container;
}


+ 2
- 1
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/AuditPurgeTaskProcessor.java 查看文件

@@ -32,6 +32,7 @@ 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 static org.sonar.db.ce.CeTaskTypes.AUDIT_PURGE;
@@ -72,7 +73,7 @@ public class AuditPurgeTaskProcessor implements CeTaskProcessor {

public static final class AuditPurgeComputationSteps extends AbstractComputationSteps {

public AuditPurgeComputationSteps(ContainerPopulator.Container container) {
public AuditPurgeComputationSteps(Container container) {
super(container);
}


+ 2
- 1
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/IssueSyncTaskProcessor.java 查看文件

@@ -33,6 +33,7 @@ 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 static org.sonar.db.ce.CeTaskTypes.BRANCH_ISSUE_SYNC;
@@ -73,7 +74,7 @@ public class IssueSyncTaskProcessor implements CeTaskProcessor {

public static final class SyncComputationSteps extends AbstractComputationSteps {

public SyncComputationSteps(ContainerPopulator.Container container) {
public SyncComputationSteps(Container container) {
super(container);
}


+ 2
- 2
server/sonar-ce-task/src/main/java/org/sonar/ce/task/container/TaskContainer.java 查看文件

@@ -22,12 +22,12 @@ 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.ContainerPopulator;
import org.sonar.core.platform.Container;

/**
* The Compute Engine task container. Created for a specific parent {@link ComponentContainer} and a specific {@link CeTask}.
*/
public interface TaskContainer extends ContainerPopulator.Container, AutoCloseable {
public interface TaskContainer extends Container, AutoCloseable {

ComponentContainer getParent();


+ 2
- 2
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/engine/MigrationContainer.java 查看文件

@@ -19,7 +19,7 @@
*/
package org.sonar.server.platform.db.migration.engine;

import org.sonar.core.platform.ContainerPopulator;
import org.sonar.core.platform.Container;

/**
* A dedicated container used to run DB migrations where all components are lazily instantiated.
@@ -32,7 +32,7 @@ import org.sonar.core.platform.ContainerPopulator;
* classes only they really are to be executed.
* </p>
*/
public interface MigrationContainer extends ContainerPopulator.Container {
public interface MigrationContainer extends Container {

/**
* Cleans up resources after migration has run.

+ 2
- 0
sonar-core/build.gradle 查看文件

@@ -16,10 +16,12 @@ dependencies {
compile 'commons-codec:commons-codec'
compile 'commons-io:commons-io'
compile 'commons-lang:commons-lang'
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'
compile project(path: ':sonar-plugin-api', configuration: 'shadow')
compile project(':sonar-plugin-api-impl')


+ 16
- 18
sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsInstaller.java 查看文件

@@ -30,7 +30,7 @@ import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.utils.AnnotationUtils;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.ExtensionContainer;

import static java.util.Objects.requireNonNull;

@@ -41,8 +41,7 @@ public abstract class CoreExtensionsInstaller {
private final CoreExtensionRepository coreExtensionRepository;
private final Class<? extends Annotation> supportedAnnotationType;

protected CoreExtensionsInstaller(SonarRuntime sonarRuntime, CoreExtensionRepository coreExtensionRepository,
Class<? extends Annotation> supportedAnnotationType) {
protected CoreExtensionsInstaller(SonarRuntime sonarRuntime, CoreExtensionRepository coreExtensionRepository, Class<? extends Annotation> supportedAnnotationType) {
this.sonarRuntime = sonarRuntime;
this.coreExtensionRepository = coreExtensionRepository;
this.supportedAnnotationType = supportedAnnotationType;
@@ -63,12 +62,12 @@ public abstract class CoreExtensionsInstaller {
* @param additionalSideFilter applied on top of filtering on {@link #supportedAnnotationType} to decide whether
* extension should be added to container as an object or only as a PropertyDefinition.
*/
public void install(ComponentContainer container, Predicate<Object> extensionFilter, Predicate<Object> additionalSideFilter) {
public void install(ExtensionContainer container, Predicate<Object> extensionFilter, Predicate<Object> additionalSideFilter) {
coreExtensionRepository.loadedCoreExtensions()
.forEach(coreExtension -> install(container, extensionFilter, additionalSideFilter, coreExtension));
}

private void install(ComponentContainer container, Predicate<Object> extensionFilter, Predicate<Object> additionalSideFilter, CoreExtension coreExtension) {
private void install(ExtensionContainer container, Predicate<Object> extensionFilter, Predicate<Object> additionalSideFilter, CoreExtension coreExtension) {
String coreExtensionName = coreExtension.getName();
try {
addDeclaredExtensions(container, extensionFilter, additionalSideFilter, coreExtension);
@@ -80,33 +79,23 @@ public abstract class CoreExtensionsInstaller {
}
}

private void addDeclaredExtensions(ComponentContainer container, Predicate<Object> extensionFilter,
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);
}

private <T> boolean addSupportedExtension(ComponentContainer container, Predicate<Object> additionalSideFilter,
String extensionCategory, T component) {
if (hasSupportedAnnotation(component) && additionalSideFilter.test(component)) {
container.addExtension(extensionCategory, component);
return true;
}
return false;
}

private <T> boolean hasSupportedAnnotation(T component) {
return AnnotationUtils.getAnnotation(component, supportedAnnotationType) != null;
}

private class ContextImpl implements CoreExtension.Context {
private final ComponentContainer container;
private final ExtensionContainer container;
private final Predicate<Object> extensionFilter;
private final Predicate<Object> additionalSideFilter;
private final String extensionCategory;

public ContextImpl(ComponentContainer container, Predicate<Object> extensionFilter,
Predicate<Object> additionalSideFilter, String extensionCategory) {
public ContextImpl(ExtensionContainer container, Predicate<Object> extensionFilter, Predicate<Object> additionalSideFilter, String extensionCategory) {
this.container = container;
this.extensionFilter = extensionFilter;
this.additionalSideFilter = additionalSideFilter;
@@ -150,5 +139,14 @@ public abstract class CoreExtensionsInstaller {
components.forEach(this::addExtension);
return this;
}

private <T> boolean addSupportedExtension(ExtensionContainer container, Predicate<Object> additionalSideFilter,
String extensionCategory, T component) {
if (hasSupportedAnnotation(component) && additionalSideFilter.test(component)) {
container.addExtension(extensionCategory, component);
return true;
}
return false;
}
}
}

+ 2
- 0
sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsLoader.java 查看文件

@@ -22,6 +22,7 @@ package org.sonar.core.extension;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.util.stream.MoreCollectors;
@@ -37,6 +38,7 @@ public class CoreExtensionsLoader {
private final CoreExtensionRepository coreExtensionRepository;
private final ServiceLoaderWrapper serviceLoaderWrapper;

@Inject
public CoreExtensionsLoader(CoreExtensionRepository coreExtensionRepository) {
this(coreExtensionRepository, new ServiceLoaderWrapper());
}

+ 3
- 0
sonar-core/src/main/java/org/sonar/core/metric/ScannerMetrics.java 查看文件

@@ -30,6 +30,7 @@ import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.Metrics;
import org.sonar.api.scanner.ScannerSide;
import org.springframework.beans.factory.annotation.Autowired;

import static org.sonar.api.measures.CoreMetrics.CLASSES;
import static org.sonar.api.measures.CoreMetrics.COGNITIVE_COMPLEXITY;
@@ -96,10 +97,12 @@ public class ScannerMetrics {

private final Set<Metric> metrics;

@Autowired(required = false)
public ScannerMetrics() {
this.metrics = ALLOWED_CORE_METRICS;
}

@Autowired(required = false)
public ScannerMetrics(Metrics[] metricsRepositories) {
this.metrics = Stream.concat(getPluginMetrics(metricsRepositories), ALLOWED_CORE_METRICS.stream()).collect(toSet());
}

+ 9
- 3
sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java 查看文件

@@ -49,7 +49,7 @@ import static java.util.Optional.ofNullable;
@ScannerSide
@ServerSide
@ComputeEngineSide
public class ComponentContainer implements ContainerPopulator.Container {
public class ComponentContainer implements ExtensionContainer {
public static final int COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER = 2;

private static final class ExtendedDefaultPicoContainer extends DefaultPicoContainer {
@@ -235,6 +235,7 @@ public class ComponentContainer implements ContainerPopulator.Container {
return this;
}

@Override
public ComponentContainer addExtension(@Nullable PluginInfo pluginInfo, Object extension) {
Object key = componentKeys.of(extension);
try {
@@ -246,6 +247,7 @@ public class ComponentContainer implements ContainerPopulator.Container {
return this;
}

@Override
public ComponentContainer addExtension(@Nullable String defaultCategory, Object extension) {
Object key = componentKeys.of(extension);
try {
@@ -264,12 +266,16 @@ public class ComponentContainer implements ContainerPopulator.Container {
return getName(extension.getClass());
}

public void declareExtension(@Nullable PluginInfo pluginInfo, Object extension) {
@Override
public ComponentContainer declareExtension(@Nullable PluginInfo pluginInfo, Object extension) {
declareExtension(pluginInfo != null ? pluginInfo.getName() : "", extension);
return this;
}

public void declareExtension(@Nullable String defaultCategory, Object extension) {
@Override
public ComponentContainer declareExtension(@Nullable String defaultCategory, Object extension) {
propertyDefinitions.addComponent(extension, ofNullable(defaultCategory).orElse(""));
return this;
}

public ComponentContainer addPicoAdapter(ComponentAdapter<?> adapter) {

+ 12
- 4
sonar-core/src/main/java/org/sonar/core/platform/ComponentKeys.java 查看文件

@@ -26,19 +26,27 @@ import org.sonar.core.util.Uuids;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;

class ComponentKeys {
public class ComponentKeys {
private static final Logger LOG = Loggers.get(ComponentKeys.class);
private static final Pattern IDENTITY_HASH_PATTERN = Pattern.compile(".+@[a-f0-9]+");
private final Set<Class> objectsWithoutToString = new HashSet<>();

Object of(Object component) {
return of(component, Loggers.get(ComponentKeys.class));
return of(component, LOG);
}

Object of(Object component, Logger log) {
if (component instanceof Class) {
return component;
}
return ofInstance(component, log);
}

public String ofInstance(Object component) {
return ofInstance(component, LOG);
}

String ofInstance(Object component, Logger log) {
String key = component.toString();
if (IDENTITY_HASH_PATTERN.matcher(key).matches()) {
if (!objectsWithoutToString.add(component.getClass())) {
@@ -46,6 +54,6 @@ class ComponentKeys {
}
key += Uuids.create();
}
return new StringBuilder().append(component.getClass().getCanonicalName()).append("-").append(key).toString();
return component.getClass().getCanonicalName() + "-" + key;
}
}

+ 34
- 0
sonar-core/src/main/java/org/sonar/core/platform/Container.java 查看文件

@@ -0,0 +1,34 @@
/*
* 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.List;

public interface Container {
Container add(Object... objects);

Container addSingletons(Iterable<?> components);

<T> T getComponentByType(Class<T> type);

<T> List<T> getComponentsByType(Class<T> type);

Container getParent();
}

+ 1
- 13
sonar-core/src/main/java/org/sonar/core/platform/ContainerPopulator.java 查看文件

@@ -19,19 +19,7 @@
*/
package org.sonar.core.platform;

import java.util.List;

@FunctionalInterface
public interface ContainerPopulator<T extends ContainerPopulator.Container> {
public interface ContainerPopulator<T extends Container> {
void populateContainer(T container);

interface Container {
Container add(Object... objects);

Container addSingletons(Iterable<?> components);

<T> T getComponentByType(Class<T> type);

<T> List<T> getComponentsByType(Class<T> type);
}
}

+ 36
- 0
sonar-core/src/main/java/org/sonar/core/platform/ExtensionContainer.java 查看文件

@@ -0,0 +1,36 @@
/*
* 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.CheckForNull;
import javax.annotation.Nullable;

public interface ExtensionContainer extends Container {
ExtensionContainer addExtension(@Nullable PluginInfo pluginInfo, Object extension);

ExtensionContainer addExtension(@Nullable String defaultCategory, Object extension);

ExtensionContainer declareExtension(@Nullable PluginInfo pluginInfo, Object extension);

ExtensionContainer declareExtension(@Nullable String defaultCategory, Object extension);

@CheckForNull
ExtensionContainer getParent();
}

+ 2
- 0
sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java 查看文件

@@ -39,6 +39,7 @@ import java.util.List;
import java.util.Optional;
import java.util.zip.GZIPInputStream;
import javax.annotation.Nullable;
import javax.inject.Inject;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.sonar.api.CoreProperties;
@@ -62,6 +63,7 @@ public class DefaultHttpDownloader extends HttpDownloader {
private final Integer readTimeout;
private final Integer connectTimeout;

@Inject
public DefaultHttpDownloader(Server server, Configuration config) {
this(server, config, null);
}

+ 8
- 1
sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/DefaultTempFolder.java 查看文件

@@ -23,6 +23,7 @@ import java.nio.file.FileVisitResult;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import org.apache.commons.io.FileUtils;
import org.sonar.api.Startable;
import org.sonar.api.utils.TempFolder;

import javax.annotation.Nullable;
@@ -34,7 +35,7 @@ import java.nio.file.Path;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;

public class DefaultTempFolder implements TempFolder {
public class DefaultTempFolder implements TempFolder, Startable {
private static final Logger LOG = Loggers.get(DefaultTempFolder.class);

private final File tempDir;
@@ -101,6 +102,12 @@ public class DefaultTempFolder implements TempFolder {
}
}

@Override
public void start() {
// nothing to do
}

@Override
public void stop() {
if (deleteOnExit) {
clean();

+ 4
- 4
sonar-plugin-api/src/test/java/org/sonar/api/resources/LanguagesTest.java 查看文件

@@ -29,8 +29,8 @@ public class LanguagesTest {
@Test
public void should_add_several_times_the_same_language() {
Languages languages = new Languages(
language("fake"),
language("fake"));
language("fake"),
language("fake"));

assertThat(languages.get("fake").getKey()).isEqualTo("fake");
}
@@ -38,8 +38,8 @@ public class LanguagesTest {
@Test
public void should_get_suffixes() {
Languages languages = new Languages(
language("java", "java"),
language("php", "php4", "php5"));
language("java", "java"),
language("php", "php4", "php5"));

assertThat(languages.getSuffixes()).containsOnly("java", "php4", "php5");
assertThat(languages.getSuffixes("java")).containsOnly("java");

+ 3
- 0
sonar-scanner-engine/build.gradle 查看文件

@@ -26,6 +26,7 @@ dependencies {
compile 'com.google.protobuf:protobuf-java'
compile 'com.squareup.okhttp3:okhttp'
compile 'com.fasterxml.staxmate:staxmate'
compile 'javax.annotation:javax.annotation-api'
compile 'org.eclipse.jgit:org.eclipse.jgit'
compile 'org.tmatesoft.svnkit:svnkit'
compile 'org.picocontainer:picocontainer'
@@ -34,6 +35,8 @@ dependencies {
compile 'org.slf4j:log4j-over-slf4j'
compile 'org.slf4j:slf4j-api'
compile 'org.sonarsource.update-center:sonar-update-center-common'
compile 'org.springframework:spring-context'


compile project(':sonar-core')
compile project(':sonar-scanner-protocol')

+ 2
- 2
sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/Batch.java 查看文件

@@ -27,7 +27,7 @@ import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.sonar.api.utils.MessageException;
import org.sonar.scanner.bootstrap.GlobalContainer;
import org.sonar.scanner.bootstrap.SpringGlobalContainer;

/**
* Entry point for SonarQube Scanner API 2.1+.
@@ -69,7 +69,7 @@ public final class Batch {
public synchronized Batch doExecute(Map<String, String> scannerProperties, List<Object> components) {
configureLogging();
try {
GlobalContainer.create(scannerProperties, components).execute();
SpringGlobalContainer.create(scannerProperties, components).execute();
} catch (RuntimeException e) {
throw handleException(e);
}

+ 2
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/ProjectInfo.java 查看文件

@@ -24,8 +24,8 @@ import java.util.Date;
import java.util.Optional;
import java.util.function.Predicate;
import org.apache.commons.lang.StringUtils;
import org.picocontainer.Startable;
import org.sonar.api.CoreProperties;
import org.sonar.api.Startable;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.MessageException;
@@ -41,7 +41,7 @@ import static org.sonar.api.CoreProperties.PROJECT_VERSION_PROPERTY;
*/
public class ProjectInfo implements Startable {
private final Clock clock;
private Configuration settings;
private final Configuration settings;

private Date analysisDate;
private String projectVersion;

+ 11
- 44
sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/AnalysisTempFolderProvider.java 查看文件

@@ -22,58 +22,25 @@ package org.sonar.scanner.analysis;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.picocontainer.ComponentLifecycle;
import org.picocontainer.PicoContainer;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.impl.utils.DefaultTempFolder;
import org.sonar.api.utils.TempFolder;
import org.springframework.context.annotation.Bean;

public class AnalysisTempFolderProvider extends ProviderAdapter implements ComponentLifecycle<TempFolder> {
public class AnalysisTempFolderProvider {
static final String TMP_NAME = ".sonartmp";
private DefaultTempFolder projectTempFolder;
private boolean started = false;

@Bean("TempFolder")
public TempFolder provide(DefaultInputProject project) {
if (projectTempFolder == null) {
Path workingDir = project.getWorkDir();
Path tempDir = workingDir.normalize().resolve(TMP_NAME);
try {
Files.deleteIfExists(tempDir);
Files.createDirectories(tempDir);
} catch (IOException e) {
throw new IllegalStateException("Unable to create root temp directory " + tempDir, e);
}

projectTempFolder = new DefaultTempFolder(tempDir.toFile(), true);
}
return projectTempFolder;
}

@Override
public void start(PicoContainer container) {
started = true;
}

@Override
public void stop(PicoContainer container) {
if (projectTempFolder != null) {
projectTempFolder.stop();
Path workingDir = project.getWorkDir();
Path tempDir = workingDir.normalize().resolve(TMP_NAME);
try {
Files.deleteIfExists(tempDir);
Files.createDirectories(tempDir);
} catch (IOException e) {
throw new IllegalStateException("Unable to create root temp directory " + tempDir, e);
}
}

@Override
public void dispose(PicoContainer container) {
// nothing to do
}

@Override
public boolean componentHasLifecycle() {
return true;
}

@Override
public boolean isStarted() {
return started;
return new DefaultTempFolder(tempDir.toFile(), true);
}
}

+ 5
- 5
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/AbstractExtensionDictionary.java 查看文件

@@ -35,13 +35,13 @@ import org.sonar.api.batch.DependsUpon;
import org.sonar.api.batch.Phase;
import org.sonar.api.utils.AnnotationUtils;
import org.sonar.api.utils.dag.DirectAcyclicGraph;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.ExtensionContainer;

public abstract class AbstractExtensionDictionary {

private final ComponentContainer componentContainer;
private final ExtensionContainer componentContainer;

public AbstractExtensionDictionary(ComponentContainer componentContainer) {
protected AbstractExtensionDictionary(ExtensionContainer componentContainer) {
this.componentContainer = componentContainer;
}

@@ -78,9 +78,9 @@ public abstract class AbstractExtensionDictionary {
return extensions;
}

private static <T> void completeScannerExtensions(ComponentContainer container, List<T> extensions, Class<T> type) {
private static <T> void completeScannerExtensions(ExtensionContainer container, List<T> extensions, Class<T> type) {
extensions.addAll(container.getComponentsByType(type));
ComponentContainer parentContainer = container.getParent();
ExtensionContainer parentContainer = container.getParent();
if (parentContainer != null) {
completeScannerExtensions(parentContainer, extensions, type);
}

+ 62
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ClassDerivedBeanDefinition.java 查看文件

@@ -0,0 +1,62 @@
/*
* 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);
}
}

+ 3
- 4
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ExtensionInstaller.java 查看文件

@@ -24,7 +24,7 @@ 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.core.platform.ComponentContainer;
import org.sonar.core.platform.ExtensionContainer;
import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginRepository;

@@ -40,8 +40,7 @@ public class ExtensionInstaller {
this.bootConfiguration = bootConfiguration;
}

public ExtensionInstaller install(ComponentContainer container, ExtensionMatcher matcher) {

public ExtensionInstaller install(ExtensionContainer container, ExtensionMatcher matcher) {
// core components
for (Object o : BatchComponents.all()) {
doInstall(container, matcher, null, o);
@@ -64,7 +63,7 @@ public class ExtensionInstaller {
return this;
}

private static void doInstall(ComponentContainer container, ExtensionMatcher matcher, @Nullable PluginInfo pluginInfo, Object extension) {
private static void doInstall(ExtensionContainer container, ExtensionMatcher matcher, @Nullable PluginInfo pluginInfo, Object extension) {
if (matcher.accept(extension)) {
container.addExtension(pluginInfo, extension);
} else {

+ 1
- 3
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalConfiguration.java 查看文件

@@ -21,15 +21,13 @@ package org.sonar.scanner.bootstrap;

import java.util.Map;
import javax.annotation.concurrent.Immutable;
import org.sonar.api.config.internal.Encryption;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.internal.Encryption;
import org.sonar.scanner.config.DefaultConfiguration;

@Immutable
public class GlobalConfiguration extends DefaultConfiguration {

public GlobalConfiguration(PropertyDefinitions propertyDefinitions, Encryption encryption, Map<String, String> settings) {
super(propertyDefinitions, encryption, settings);
}

}

+ 8
- 15
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalConfigurationProvider.java 查看文件

@@ -21,22 +21,15 @@ package org.sonar.scanner.bootstrap;

import java.util.LinkedHashMap;
import java.util.Map;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.config.PropertyDefinitions;
import org.springframework.context.annotation.Bean;

public class GlobalConfigurationProvider extends ProviderAdapter {

private GlobalConfiguration globalConfig;

public GlobalConfiguration provide(GlobalServerSettings globalServerSettings, ScannerProperties scannerProps,
PropertyDefinitions propertyDefinitions) {
if (globalConfig == null) {
Map<String, String> mergedSettings = new LinkedHashMap<>();
mergedSettings.putAll(globalServerSettings.properties());
mergedSettings.putAll(scannerProps.properties());

globalConfig = new GlobalConfiguration(propertyDefinitions, scannerProps.getEncryption(), mergedSettings);
}
return globalConfig;
public class GlobalConfigurationProvider {
@Bean("GlobalConfiguration")
public GlobalConfiguration provide(GlobalServerSettings globalServerSettings, ScannerProperties scannerProps, PropertyDefinitions propertyDefinitions) {
Map<String, String> mergedSettings = new LinkedHashMap<>();
mergedSettings.putAll(globalServerSettings.properties());
mergedSettings.putAll(scannerProps.properties());
return new GlobalConfiguration(propertyDefinitions, scannerProps.getEncryption(), mergedSettings);
}
}

+ 6
- 11
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalServerSettingsProvider.java 查看文件

@@ -21,24 +21,19 @@ package org.sonar.scanner.bootstrap;

import java.util.Map;
import java.util.Optional;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.CoreProperties;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.scanner.repository.settings.GlobalSettingsLoader;
import org.springframework.context.annotation.Bean;

public class GlobalServerSettingsProvider extends ProviderAdapter {

public class GlobalServerSettingsProvider {
private static final Logger LOG = Loggers.get(GlobalServerSettingsProvider.class);

private GlobalServerSettings singleton;

@Bean("GlobalServerSettings")
public GlobalServerSettings provide(GlobalSettingsLoader loader) {
if (singleton == null) {
Map<String, String> serverSideSettings = loader.loadGlobalSettings();
singleton = new GlobalServerSettings(serverSideSettings);
Optional.ofNullable(serverSideSettings.get(CoreProperties.SERVER_ID)).ifPresent(v -> LOG.info("Server id: {}", v));
}
return singleton;
Map<String, String> serverSideSettings = loader.loadGlobalSettings();
Optional.ofNullable(serverSideSettings.get(CoreProperties.SERVER_ID)).ifPresent(v -> LOG.info("Server id: {}", v));
return new GlobalServerSettings(serverSideSettings);
}
}

+ 7
- 23
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalTempFolderProvider.java 查看文件

@@ -27,23 +27,21 @@ import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.picocontainer.ComponentLifecycle;
import org.picocontainer.PicoContainer;
import org.picocontainer.injectors.ProviderAdapter;
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 org.springframework.context.annotation.Bean;

import static org.sonar.core.util.FileUtils.deleteQuietly;

public class GlobalTempFolderProvider extends ProviderAdapter implements ComponentLifecycle<TempFolder> {
public class GlobalTempFolderProvider implements Startable {
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 boolean started = false;

private System2 system;
private DefaultTempFolder tempFolder;
@@ -56,6 +54,7 @@ public class GlobalTempFolderProvider extends ProviderAdapter implements Compone
this.system = system;
}

@Bean("TempFolder")
public TempFolder provide(ScannerProperties scannerProps) {
if (tempFolder == null) {

@@ -150,29 +149,14 @@ public class GlobalTempFolderProvider extends ProviderAdapter implements Compone
}

@Override
public void start(PicoContainer container) {
started = true;
public void start() {
// nothing to do
}

@Override
public void stop(PicoContainer container) {
public void stop() {
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;
}
}

+ 35
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/LazyBeanFactoryPostProcessor.java 查看文件

@@ -0,0 +1,35 @@
/*
* 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);
}
}
}

+ 1
- 1
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginFiles.java 查看文件

@@ -181,7 +181,7 @@ public class PluginFiles {
LOGGER.debug("Unpacking plugin {}", pluginKey);
File jar = newTempFile();
try (InputStream input = new GZIPInputStream(new BufferedInputStream(FileUtils.openInputStream(compressedFile)));
JarOutputStream output = new JarOutputStream(new BufferedOutputStream(FileUtils.openOutputStream(jar)))) {
JarOutputStream output = new JarOutputStream(new BufferedOutputStream(FileUtils.openOutputStream(jar)))) {
Pack200.newUnpacker().unpack(input, output);
} catch (IOException e) {
throw new IllegalStateException(format("Fail to download plugin [%s]. Pack200 error.", pluginKey), e);

+ 3
- 3
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionary.java 查看文件

@@ -23,7 +23,7 @@ import java.util.Collection;
import java.util.stream.Collectors;
import org.sonar.api.batch.postjob.PostJob;
import org.sonar.api.batch.postjob.PostJobContext;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.ExtensionContainer;
import org.sonar.scanner.postjob.PostJobOptimizer;
import org.sonar.scanner.postjob.PostJobWrapper;

@@ -32,8 +32,8 @@ public class PostJobExtensionDictionary extends AbstractExtensionDictionary {
private final PostJobContext postJobContext;
private final PostJobOptimizer postJobOptimizer;

public PostJobExtensionDictionary(ComponentContainer componentContainer, PostJobOptimizer postJobOptimizer, PostJobContext postJobContext) {
super(componentContainer);
public PostJobExtensionDictionary(ExtensionContainer container, PostJobOptimizer postJobOptimizer, PostJobContext postJobContext) {
super(container);
this.postJobOptimizer = postJobOptimizer;
this.postJobContext = postJobContext;
}

+ 123
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PriorityBeanFactory.java 查看文件

@@ -0,0 +1,123 @@
/*
* 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);
}
}

+ 1
- 1
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginRepository.java 查看文件

@@ -24,8 +24,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import org.picocontainer.Startable;
import org.sonar.api.Plugin;
import org.sonar.api.Startable;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.platform.ExplodedPlugin;

+ 23
- 29
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java 查看文件

@@ -19,49 +19,43 @@
*/
package org.sonar.scanner.bootstrap;

import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.CoreProperties;
import org.sonar.api.utils.System2;
import org.sonar.batch.bootstrapper.EnvironmentInformation;
import org.sonarqube.ws.client.HttpConnector;
import org.sonarqube.ws.client.WsClientFactories;
import org.springframework.context.annotation.Bean;

import static java.lang.Integer.parseInt;
import static java.lang.String.valueOf;
import static org.apache.commons.lang.StringUtils.defaultIfBlank;

public class ScannerWsClientProvider extends ProviderAdapter {

public class ScannerWsClientProvider {
static final int CONNECT_TIMEOUT_MS = 5_000;
static final String READ_TIMEOUT_SEC_PROPERTY = "sonar.ws.timeout";
static final int DEFAULT_READ_TIMEOUT_SEC = 60;

private DefaultScannerWsClient wsClient;

public synchronized DefaultScannerWsClient provide(final ScannerProperties scannerProps,
final EnvironmentInformation env, GlobalAnalysisMode globalMode, System2 system) {
if (wsClient == null) {
String url = defaultIfBlank(scannerProps.property("sonar.host.url"), "http://localhost:9000");
HttpConnector.Builder connectorBuilder = HttpConnector.newBuilder();

String timeoutSec = defaultIfBlank(scannerProps.property(READ_TIMEOUT_SEC_PROPERTY), valueOf(DEFAULT_READ_TIMEOUT_SEC));
String token = defaultIfBlank(system.envVariable("SONAR_TOKEN"), null);
String login = defaultIfBlank(scannerProps.property(CoreProperties.LOGIN), token);
connectorBuilder
.readTimeoutMilliseconds(parseInt(timeoutSec) * 1_000)
.connectTimeoutMilliseconds(CONNECT_TIMEOUT_MS)
.userAgent(env.toString())
.url(url)
.credentials(login, scannerProps.property(CoreProperties.PASSWORD));

// OkHttp detect 'http.proxyHost' java property, but credentials should be filled
final String proxyUser = System.getProperty("http.proxyUser", "");
if (!proxyUser.isEmpty()) {
connectorBuilder.proxyCredentials(proxyUser, System.getProperty("http.proxyPassword"));
}

wsClient = new DefaultScannerWsClient(WsClientFactories.getDefault().newClient(connectorBuilder.build()), login != null, globalMode);
@Bean("DefaultScannerWsClient")
public DefaultScannerWsClient provide(ScannerProperties scannerProps, EnvironmentInformation env, GlobalAnalysisMode globalMode, System2 system) {
String url = defaultIfBlank(scannerProps.property("sonar.host.url"), "http://localhost:9000");
HttpConnector.Builder connectorBuilder = HttpConnector.newBuilder();

String timeoutSec = defaultIfBlank(scannerProps.property(READ_TIMEOUT_SEC_PROPERTY), valueOf(DEFAULT_READ_TIMEOUT_SEC));
String token = defaultIfBlank(system.envVariable("SONAR_TOKEN"), null);
String login = defaultIfBlank(scannerProps.property(CoreProperties.LOGIN), token);
connectorBuilder
.readTimeoutMilliseconds(parseInt(timeoutSec) * 1_000)
.connectTimeoutMilliseconds(CONNECT_TIMEOUT_MS)
.userAgent(env.toString())
.url(url)
.credentials(login, scannerProps.property(CoreProperties.PASSWORD));

// OkHttp detect 'http.proxyHost' java property, but credentials should be filled
final String proxyUser = System.getProperty("http.proxyUser", "");
if (!proxyUser.isEmpty()) {
connectorBuilder.proxyCredentials(proxyUser, System.getProperty("http.proxyPassword"));
}
return wsClient;

return new DefaultScannerWsClient(WsClientFactories.getDefault().newClient(connectorBuilder.build()), login != null, globalMode);
}
}

+ 231
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringComponentContainer.java 查看文件

@@ -0,0 +1,231 @@
/*
* 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 com.google.common.collect.Lists;
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 org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator;

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());
// it won't set the name of beans created with @Bean annotated methods
this.context.setBeanNameGenerator(new FullyQualifiedAnnotationBeanNameGenerator());
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 fully qualified class name as the name of the bean
* - For instances, use the 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(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(clazz.getName(), 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
}
}

sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java → sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringGlobalContainer.java 查看文件

@@ -22,13 +22,13 @@ package org.sonar.scanner.bootstrap;
import java.time.Clock;
import java.util.List;
import java.util.Map;
import javax.annotation.Priority;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.CoreProperties;
import org.sonar.api.Plugin;
import org.sonar.api.SonarEdition;
import org.sonar.api.SonarQubeSide;
import org.sonar.api.SonarQubeVersion;
import org.sonar.api.SonarRuntime;
import org.sonar.api.internal.MetadataLoader;
import org.sonar.api.internal.SonarRuntimeImpl;
import org.sonar.api.utils.MessageException;
@@ -39,7 +39,6 @@ import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.extension.CoreExtensionRepositoryImpl;
import org.sonar.core.extension.CoreExtensionsLoader;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.PluginClassLoader;
import org.sonar.core.platform.PluginClassloaderFactory;
import org.sonar.core.platform.PluginInfo;
@@ -51,30 +50,26 @@ import org.sonar.scanner.notifications.DefaultAnalysisWarnings;
import org.sonar.scanner.platform.DefaultServer;
import org.sonar.scanner.repository.DefaultMetricsRepositoryLoader;
import org.sonar.scanner.repository.DefaultNewCodePeriodLoader;
import org.sonar.scanner.repository.MetricsRepositoryLoader;
import org.sonar.scanner.repository.MetricsRepositoryProvider;
import org.sonar.scanner.repository.NewCodePeriodLoader;
import org.sonar.scanner.repository.settings.DefaultGlobalSettingsLoader;
import org.sonar.scanner.repository.settings.GlobalSettingsLoader;
import org.sonar.scanner.scan.ProjectScanContainer;
import org.sonar.scanner.scan.SpringProjectScanContainer;

public class GlobalContainer extends ComponentContainer {
private static final Logger LOG = Loggers.get(GlobalContainer.class);
@Priority(3)
public class SpringGlobalContainer extends SpringComponentContainer {
private static final Logger LOG = Loggers.get(SpringGlobalContainer.class);
private final Map<String, String> scannerProperties;

private GlobalContainer(Map<String, String> scannerProperties) {
super();
private SpringGlobalContainer(Map<String, String> scannerProperties, List<?> addedExternally) {
super(addedExternally);
this.scannerProperties = scannerProperties;
}

public static GlobalContainer create(Map<String, String> scannerProperties, List<?> extensions) {
GlobalContainer container = new GlobalContainer(scannerProperties);
container.add(extensions);
return container;
public static SpringGlobalContainer create(Map<String, String> scannerProperties, List<?> extensions) {
return new SpringGlobalContainer(scannerProperties, extensions);
}

@Override
protected void doBeforeStart() {
public void doBeforeStart() {
ScannerProperties rawScannerProperties = new ScannerProperties(scannerProperties);
GlobalAnalysisMode globalMode = new GlobalAnalysisMode(rawScannerProperties);
add(rawScannerProperties);
@@ -100,20 +95,22 @@ public class GlobalContainer extends ComponentContainer {
new ScannerWsClientProvider(),
DefaultServer.class,
new GlobalTempFolderProvider(),
DefaultHttpDownloader.class,
analysisWarnings,
UriReader.class,
PluginFiles.class,
System2.INSTANCE,
Clock.systemDefaultZone(),
new MetricsRepositoryProvider(),
UuidFactoryImpl.INSTANCE);
addIfMissing(SonarRuntimeImpl.forSonarQube(apiVersion, SonarQubeSide.SCANNER, edition), SonarRuntime.class);
addIfMissing(ScannerPluginInstaller.class, PluginInstaller.class);
add(CoreExtensionRepositoryImpl.class, CoreExtensionsLoader.class, ScannerCoreExtensionsInstaller.class);
addIfMissing(DefaultGlobalSettingsLoader.class, GlobalSettingsLoader.class);
addIfMissing(DefaultNewCodePeriodLoader.class, NewCodePeriodLoader.class);
addIfMissing(DefaultMetricsRepositoryLoader.class, MetricsRepositoryLoader.class);
UuidFactoryImpl.INSTANCE,
DefaultHttpDownloader.class,
SonarRuntimeImpl.forSonarQube(apiVersion, SonarQubeSide.SCANNER, edition),
ScannerPluginInstaller.class,
CoreExtensionRepositoryImpl.class,
CoreExtensionsLoader.class,
ScannerCoreExtensionsInstaller.class,
DefaultGlobalSettingsLoader.class,
DefaultNewCodePeriodLoader.class,
DefaultMetricsRepositoryLoader.class);
}

@Override
@@ -133,7 +130,7 @@ public class GlobalContainer extends ComponentContainer {
if (!analysisMode.equals("publish")) {
throw MessageException.of("The preview mode, along with the 'sonar.analysis.mode' parameter, is no more supported. You should stop using this parameter.");
}
new ProjectScanContainer(this).execute();
new SpringProjectScanContainer(this).execute();

LOG.info("Analysis total time: {}", formatTime(System.currentTimeMillis() - startTime));
}
@@ -147,8 +144,7 @@ public class GlobalContainer extends ComponentContainer {
}

private void loadCoreExtensions() {
CoreExtensionsLoader loader = getComponentByType(CoreExtensionsLoader.class);
loader.load();
getComponentByType(CoreExtensionsLoader.class).load();
}

static String formatTime(long time) {
@@ -166,5 +162,4 @@ public class GlobalContainer extends ComponentContainer {
}
return String.format(format, h, m, s, ms);
}

}

+ 60
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/StartableBeanPostProcessor.java 查看文件

@@ -0,0 +1,60 @@
/*
* 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);
}
}
}

+ 3
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationProvider.java 查看文件

@@ -23,17 +23,18 @@ import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.config.Configuration;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.springframework.context.annotation.Bean;

public class CiConfigurationProvider extends ProviderAdapter {
public class CiConfigurationProvider {

private static final Logger LOG = Loggers.get(CiConfigurationProvider.class);
private static final String PROP_DISABLED = "sonar.ci.autoconfig.disabled";

@Bean("CiConfiguration")
public CiConfiguration provide(Configuration configuration, CiVendor[] ciVendors) {
boolean disabled = configuration.getBoolean(PROP_DISABLED).orElse(false);
if (disabled) {

+ 3
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/cpd/CpdExecutor.java 查看文件

@@ -32,6 +32,7 @@ import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.fs.internal.DefaultInputComponent;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
@@ -71,12 +72,12 @@ public class CpdExecutor {
private int count = 0;
private int total;

@Inject
public CpdExecutor(CpdSettings settings, SonarCpdBlockIndex index, ReportPublisher publisher, InputComponentStore inputComponentCache) {
this(settings, index, publisher, inputComponentCache, Executors.newSingleThreadExecutor());
}

public CpdExecutor(CpdSettings settings, SonarCpdBlockIndex index, ReportPublisher publisher, InputComponentStore inputComponentCache,
ExecutorService executorService) {
public CpdExecutor(CpdSettings settings, SonarCpdBlockIndex index, ReportPublisher publisher, InputComponentStore inputComponentCache, ExecutorService executorService) {
this.settings = settings;
this.index = index;
this.publisher = publisher;

+ 3
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/IssueFilters.java 查看文件

@@ -25,6 +25,7 @@ import org.sonar.api.scan.issue.filter.FilterableIssue;
import org.sonar.api.scan.issue.filter.IssueFilter;
import org.sonar.api.scan.issue.filter.IssueFilterChain;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.springframework.beans.factory.annotation.Autowired;

/**
* @deprecated since 7.6, {@link IssueFilter} is deprecated
@@ -34,11 +35,13 @@ public class IssueFilters {
private final IssueFilterChain filterChain;
private final DefaultInputProject project;

@Autowired(required = false)
public IssueFilters(DefaultInputProject project, IssueFilter[] exclusionFilters) {
this.project = project;
this.filterChain = new DefaultIssueFilterChain(exclusionFilters);
}

@Autowired(required = false)
public IssueFilters(DefaultInputProject project) {
this(project, new IssueFilter[0]);
}

+ 2
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisObserver.java 查看文件

@@ -21,13 +21,13 @@ package org.sonar.scanner.mediumtest;

import org.sonar.api.ExtensionPoint;
import org.sonar.api.scanner.ScannerSide;
import org.sonar.scanner.scan.ProjectScanContainer;
import org.sonar.scanner.scan.SpringProjectScanContainer;

@ScannerSide
@ExtensionPoint
@FunctionalInterface
public interface AnalysisObserver {

void analysisCompleted(ProjectScanContainer container);
void analysisCompleted(SpringProjectScanContainer container);

}

+ 4
- 8
sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisObservers.java 查看文件

@@ -19,22 +19,18 @@
*/
package org.sonar.scanner.mediumtest;

import org.sonar.scanner.scan.ProjectScanContainer;
import org.sonar.scanner.scan.SpringProjectScanContainer;

public class AnalysisObservers {

private AnalysisObserver[] observers;
private ProjectScanContainer projectScanContainer;
private final AnalysisObserver[] observers;
private final SpringProjectScanContainer projectScanContainer;

public AnalysisObservers(ProjectScanContainer projectScanContainer, AnalysisObserver... observers) {
public AnalysisObservers(SpringProjectScanContainer projectScanContainer, AnalysisObserver... observers) {
this.projectScanContainer = projectScanContainer;
this.observers = observers;
}

public AnalysisObservers(ProjectScanContainer projectScanContainer) {
this(projectScanContainer, new AnalysisObserver[0]);
}

public void notifyEndOfScanTask() {
for (AnalysisObserver analysisObserver : observers) {
analysisObserver.analysisCompleted(projectScanContainer);

+ 3
- 3
sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java 查看文件

@@ -43,7 +43,7 @@ import org.sonar.scanner.protocol.output.ScannerReport.Symbol;
import org.sonar.scanner.protocol.output.ScannerReportReader;
import org.sonar.scanner.report.ReportPublisher;
import org.sonar.scanner.report.ScannerReportUtils;
import org.sonar.scanner.scan.ProjectScanContainer;
import org.sonar.scanner.scan.SpringProjectScanContainer;
import org.sonar.scanner.scan.filesystem.InputComponentStore;

public class AnalysisResult implements AnalysisObserver {
@@ -55,7 +55,7 @@ public class AnalysisResult implements AnalysisObserver {
private ScannerReportReader reader;

@Override
public void analysisCompleted(ProjectScanContainer container) {
public void analysisCompleted(SpringProjectScanContainer container) {
LOG.info("Store analysis results in memory for later assertions in medium test");
ReportPublisher reportPublisher = container.getComponentByType(ReportPublisher.class);
reader = new ScannerReportReader(reportPublisher.getReportDir().toFile());
@@ -69,7 +69,7 @@ public class AnalysisResult implements AnalysisObserver {
return reader;
}

private void storeFs(ProjectScanContainer container) {
private void storeFs(SpringProjectScanContainer container) {
InputComponentStore inputFileCache = container.getComponentByType(InputComponentStore.class);
for (InputFile inputPath : inputFileCache.inputFiles()) {
inputFilesByKeys.put(((DefaultInputFile) inputPath).getProjectRelativePath(), inputPath);

+ 2
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/FakePluginInstaller.java 查看文件

@@ -24,11 +24,13 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Priority;
import org.sonar.api.Plugin;
import org.sonar.core.platform.PluginInfo;
import org.sonar.scanner.bootstrap.PluginInstaller;
import org.sonar.scanner.bootstrap.ScannerPlugin;

@Priority(1)
public class FakePluginInstaller implements PluginInstaller {

private final Map<String, ScannerPlugin> pluginsByKeys = new HashMap<>();

+ 1
- 1
sonar-scanner-engine/src/main/java/org/sonar/scanner/qualitygate/QualityGateCheck.java 查看文件

@@ -23,7 +23,7 @@ import java.io.InputStream;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.EnumSet;
import org.picocontainer.Startable;
import org.sonar.api.Startable;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;

+ 1
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java 查看文件

@@ -42,8 +42,7 @@ public class ContextPropertiesPublisher implements ReportPublisherStep {
private final ScmConfiguration scmConfiguration;
private final CiConfiguration ciConfiguration;

public ContextPropertiesPublisher(ContextPropertiesCache cache, DefaultConfiguration config, ScmConfiguration scmConfiguration,
CiConfiguration ciConfiguration) {
public ContextPropertiesPublisher(ContextPropertiesCache cache, DefaultConfiguration config, ScmConfiguration scmConfiguration, CiConfiguration ciConfiguration) {
this.cache = cache;
this.config = config;
this.scmConfiguration = scmConfiguration;

+ 4
- 4
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java 查看文件

@@ -33,7 +33,7 @@ import java.util.Map;
import javax.annotation.Nullable;
import okhttp3.HttpUrl;
import org.apache.commons.io.FileUtils;
import org.picocontainer.Startable;
import org.sonar.api.Startable;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.TempFolder;
@@ -97,13 +97,13 @@ public class ReportPublisher implements Startable {
this.branchConfiguration = branchConfiguration;
this.properties = properties;
this.ceTaskReportDataHolder = ceTaskReportDataHolder;
this.reportDir = moduleHierarchy.root().getWorkDir().resolve("scanner-report");
this.writer = new ScannerReportWriter(reportDir.toFile());
this.reader = new ScannerReportReader(reportDir.toFile());
}

@Override
public void start() {
reportDir = moduleHierarchy.root().getWorkDir().resolve("scanner-report");
writer = new ScannerReportWriter(reportDir.toFile());
reader = new ScannerReportReader(reportDir.toFile());
contextPublisher.init(writer);

if (!analysisMode.isMediumTest()) {

+ 6
- 8
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/MetricsRepositoryProvider.java 查看文件

@@ -19,23 +19,21 @@
*/
package org.sonar.scanner.repository;

import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.springframework.context.annotation.Bean;

public class MetricsRepositoryProvider extends ProviderAdapter {
public class MetricsRepositoryProvider {

private static final Logger LOG = Loggers.get(MetricsRepositoryProvider.class);
private static final String LOG_MSG = "Load metrics repository";
private MetricsRepository metricsRepository;

@Bean("MetricsRepository")
public MetricsRepository provide(MetricsRepositoryLoader loader) {
if (metricsRepository == null) {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
metricsRepository = loader.load();
profiler.stopInfo();
}
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
MetricsRepository metricsRepository = loader.load();
profiler.stopInfo();
return metricsRepository;
}
}

+ 6
- 9
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfilesProvider.java 查看文件

@@ -19,25 +19,22 @@
*/
package org.sonar.scanner.repository;

import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.scanner.bootstrap.ScannerProperties;
import org.sonar.scanner.rule.QualityProfiles;
import org.springframework.context.annotation.Bean;

public class QualityProfilesProvider extends ProviderAdapter {
public class QualityProfilesProvider {
private static final Logger LOG = Loggers.get(QualityProfilesProvider.class);
private static final String LOG_MSG = "Load quality profiles";
private QualityProfiles profiles = null;

@Bean("QualityProfiles")
public QualityProfiles provide(QualityProfileLoader loader, ScannerProperties props) {
if (this.profiles == null) {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
profiles = new QualityProfiles(loader.load(props.getProjectKey()));
profiler.stopInfo();
}

Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
QualityProfiles profiles = new QualityProfiles(loader.load(props.getProjectKey()));
profiler.stopInfo();
return profiles;
}


+ 1
- 1
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/DefaultLanguagesRepository.java 查看文件

@@ -24,7 +24,7 @@ import java.util.ArrayList;
import java.util.Collection;
import javax.annotation.CheckForNull;
import javax.annotation.concurrent.Immutable;
import org.picocontainer.Startable;
import org.sonar.api.Startable;
import org.sonar.api.resources.Languages;

/**

+ 3
- 1
sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/settings/DefaultGlobalSettingsLoader.java 查看文件

@@ -20,11 +20,13 @@
package org.sonar.scanner.repository.settings;

import java.util.Map;
import javax.inject.Inject;
import org.sonar.scanner.bootstrap.DefaultScannerWsClient;

public class DefaultGlobalSettingsLoader extends AbstractSettingsLoader implements GlobalSettingsLoader {

public DefaultGlobalSettingsLoader(final DefaultScannerWsClient wsClient) {
@Inject
public DefaultGlobalSettingsLoader(DefaultScannerWsClient wsClient) {
super(wsClient);
}


+ 7
- 9
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesProvider.java 查看文件

@@ -25,7 +25,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.rule.LoadedActiveRule;
import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
import org.sonar.api.batch.rule.internal.DefaultActiveRules;
@@ -34,23 +33,22 @@ import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.springframework.context.annotation.Bean;

/**
* Loads the rules that are activated on the Quality profiles
* used by the current project and builds {@link org.sonar.api.batch.rule.ActiveRules}.
*/
public class ActiveRulesProvider extends ProviderAdapter {
public class ActiveRulesProvider {
private static final Logger LOG = Loggers.get(ActiveRulesProvider.class);
private static final String LOG_MSG = "Load active rules";
private DefaultActiveRules singleton = null;

@Bean("ActiveRules")
public DefaultActiveRules provide(ActiveRulesLoader loader, QualityProfiles qProfiles) {
if (singleton == null) {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
singleton = load(loader, qProfiles);
profiler.stopInfo();
}
return singleton;
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
DefaultActiveRules activeRules = load(loader, qProfiles);
profiler.stopInfo();
return activeRules;
}

private static DefaultActiveRules load(ActiveRulesLoader loader, QualityProfiles qProfiles) {

+ 4
- 12
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RulesProvider.java 查看文件

@@ -20,29 +20,22 @@
package org.sonar.scanner.rule;

import java.util.List;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.rule.internal.NewRule;
import org.sonar.api.batch.rule.Rules;
import org.sonar.api.batch.rule.internal.NewRule;
import org.sonar.api.batch.rule.internal.RulesBuilder;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonarqube.ws.Rules.ListResponse.Rule;
import org.springframework.context.annotation.Bean;

public class RulesProvider extends ProviderAdapter {
public class RulesProvider {
private static final Logger LOG = Loggers.get(RulesProvider.class);
private static final String LOG_MSG = "Load server rules";
private Rules singleton = null;

@Bean("Rules")
public Rules provide(RulesLoader ref) {
if (singleton == null) {
singleton = load(ref);
}
return singleton;
}

private static Rules load(RulesLoader ref) {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
List<Rule> loadedRules = ref.load();
RulesBuilder builder = new RulesBuilder();
@@ -54,7 +47,6 @@ public class RulesProvider extends ProviderAdapter {
}

profiler.stopInfo();

return builder.build();
}
}

+ 16
- 17
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputModuleHierarchyProvider.java 查看文件

@@ -22,32 +22,31 @@ package org.sonar.scanner.scan;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.scanner.scan.filesystem.ScannerComponentIdGenerator;
import org.springframework.context.annotation.Bean;

public class InputModuleHierarchyProvider extends ProviderAdapter {
public class InputModuleHierarchyProvider {

private static final Logger LOG = Loggers.get(InputModuleHierarchyProvider.class);

private DefaultInputModuleHierarchy hierarchy = null;

public DefaultInputModuleHierarchy provide(ScannerComponentIdGenerator scannerComponentIdGenerator, DefaultInputProject project) {
if (hierarchy == null) {
LOG.debug("Creating module hierarchy");
DefaultInputModule root = createModule(project.definition(), project.scannerId());
Map<DefaultInputModule, DefaultInputModule> parents = createChildren(root, scannerComponentIdGenerator, new HashMap<>());
if (parents.isEmpty()) {
hierarchy = new DefaultInputModuleHierarchy(root);
} else {
hierarchy = new DefaultInputModuleHierarchy(root, parents);
}
@Bean("DefaultInputModuleHierarchy")
public DefaultInputModuleHierarchy provide(ScannerComponentIdGenerator scannerComponentIdGenerator, WorkDirectoriesInitializer workDirectoriesInit, DefaultInputProject project) {
LOG.debug("Creating module hierarchy");
DefaultInputModule root = createModule(project.definition(), project.scannerId());
Map<DefaultInputModule, DefaultInputModule> parents = createChildren(root, scannerComponentIdGenerator, new HashMap<>());
DefaultInputModuleHierarchy inputModuleHierarchy;
if (parents.isEmpty()) {
inputModuleHierarchy = new DefaultInputModuleHierarchy(root);
} else {
inputModuleHierarchy = new DefaultInputModuleHierarchy(root, parents);
}
return hierarchy;
workDirectoriesInit.execute(inputModuleHierarchy);
return inputModuleHierarchy;
}

private static Map<DefaultInputModule, DefaultInputModule> createChildren(DefaultInputModule parent, ScannerComponentIdGenerator scannerComponentIdGenerator,

+ 14
- 18
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputProjectProvider.java 查看文件

@@ -20,36 +20,32 @@
package org.sonar.scanner.scan;

import java.util.Locale;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.scanner.scan.filesystem.ScannerComponentIdGenerator;
import org.springframework.context.annotation.Bean;

public class InputProjectProvider extends ProviderAdapter {

public class InputProjectProvider {
private static final Logger LOG = Loggers.get(InputProjectProvider.class);

private DefaultInputProject project = null;

@Bean("DefaultInputProject")
public DefaultInputProject provide(ProjectBuildersExecutor projectBuildersExecutor, ProjectReactorValidator validator,
ProjectReactor projectReactor, ScannerComponentIdGenerator scannerComponentIdGenerator) {
if (project == null) {
// 1 Apply project builders
projectBuildersExecutor.execute(projectReactor);
// 1 Apply project builders
projectBuildersExecutor.execute(projectReactor);

// 2 Validate final reactor
validator.validate(projectReactor);
// 2 Validate final reactor
validator.validate(projectReactor);

// 3 Create project
project = new DefaultInputProject(projectReactor.getRoot(), scannerComponentIdGenerator.getAsInt());
// 3 Create project
DefaultInputProject project = new DefaultInputProject(projectReactor.getRoot(), scannerComponentIdGenerator.getAsInt());

LOG.info("Project key: {}", project.key());
LOG.info("Base dir: {}", project.getBaseDir().toAbsolutePath().toString());
LOG.info("Working dir: {}", project.getWorkDir().toAbsolutePath().toString());
LOG.debug("Project global encoding: {}, default locale: {}", project.getEncoding().displayName(), Locale.getDefault());
}
LOG.info("Project key: {}", project.key());
LOG.info("Base dir: {}", project.getBaseDir().toAbsolutePath().toString());
LOG.info("Working dir: {}", project.getWorkDir().toAbsolutePath().toString());
LOG.debug("Project global encoding: {}, default locale: {}", project.getEncoding().displayName(), Locale.getDefault());
return project;
}
}

+ 36
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguagesProvider.java 查看文件

@@ -0,0 +1,36 @@
/*
* 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]));
}
}

+ 1
- 3
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleConfiguration.java 查看文件

@@ -20,14 +20,12 @@
package org.sonar.scanner.scan;

import java.util.Map;
import org.sonar.api.config.internal.Encryption;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.internal.Encryption;
import org.sonar.scanner.config.DefaultConfiguration;

public class ModuleConfiguration extends DefaultConfiguration {

public ModuleConfiguration(PropertyDefinitions propertyDefinitions, Encryption encryption, Map<String, String> props) {
super(propertyDefinitions, encryption, props);
}

}

+ 9
- 15
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleConfigurationProvider.java 查看文件

@@ -23,28 +23,22 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.scanner.bootstrap.GlobalConfiguration;
import org.sonar.scanner.bootstrap.GlobalServerSettings;
import org.sonar.api.batch.fs.internal.DefaultInputModule;

public class ModuleConfigurationProvider extends ProviderAdapter {

private ModuleConfiguration moduleConfiguration;
import org.springframework.context.annotation.Bean;

public class ModuleConfigurationProvider {
@Bean("ModuleConfiguration")
public ModuleConfiguration provide(GlobalConfiguration globalConfig, DefaultInputModule module, GlobalServerSettings globalServerSettings,
ProjectServerSettings projectServerSettings) {
if (moduleConfiguration == null) {

Map<String, String> settings = new LinkedHashMap<>();
settings.putAll(globalServerSettings.properties());
settings.putAll(projectServerSettings.properties());
addScannerSideProperties(settings, module.definition());
Map<String, String> settings = new LinkedHashMap<>();
settings.putAll(globalServerSettings.properties());
settings.putAll(projectServerSettings.properties());
addScannerSideProperties(settings, module.definition());

moduleConfiguration = new ModuleConfiguration(globalConfig.getDefinitions(), globalConfig.getEncryption(), settings);
}
return moduleConfiguration;
return new ModuleConfiguration(globalConfig.getDefinitions(), globalConfig.getEncryption(), settings);
}

private static void addScannerSideProperties(Map<String, String> settings, ProjectDefinition project) {

+ 1
- 1
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java 查看文件

@@ -19,7 +19,7 @@
*/
package org.sonar.scanner.scan;

import org.picocontainer.Startable;
import org.sonar.api.Startable;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.scanner.fs.InputModuleHierarchy;
import org.sonar.scanner.scan.filesystem.InputComponentStore;

+ 2
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableModuleSettings.java 查看文件

@@ -22,6 +22,7 @@ package org.sonar.scanner.scan;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Priority;
import org.sonar.api.config.internal.Settings;

import static java.util.Objects.requireNonNull;
@@ -30,6 +31,7 @@ import static java.util.Objects.requireNonNull;
* @deprecated since 6.5 {@link ModuleConfiguration} used to be mutable, so keep a mutable copy for backward compatibility.
*/
@Deprecated
@Priority(1)
public class MutableModuleSettings extends Settings {

private final Map<String, String> properties = new HashMap<>();

+ 4
- 8
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableProjectReactorProvider.java 查看文件

@@ -19,16 +19,12 @@
*/
package org.sonar.scanner.scan;

import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.springframework.context.annotation.Bean;

public class MutableProjectReactorProvider extends ProviderAdapter {
private ProjectReactor reactor = null;

public class MutableProjectReactorProvider {
@Bean("ProjectReactor")
public ProjectReactor provide(ProjectReactorBuilder builder) {
if (reactor == null) {
reactor = builder.execute();
}
return reactor;
return builder.execute();
}
}

+ 3
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableProjectSettings.java 查看文件

@@ -25,12 +25,15 @@ import java.util.Optional;
import org.sonar.api.config.internal.Settings;
import org.sonar.scanner.bootstrap.GlobalConfiguration;

import javax.annotation.Priority;

import static java.util.Objects.requireNonNull;

/**
* @deprecated since 6.5 {@link ProjectConfiguration} used to be mutable, so keep a mutable copy for backward compatibility.
*/
@Deprecated
@Priority(2)
public class MutableProjectSettings extends Settings {

private final Map<String, String> properties = new HashMap<>();

+ 3
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectBuildersExecutor.java 查看文件

@@ -28,6 +28,7 @@ import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.scanner.bootstrap.GlobalConfiguration;
import org.springframework.beans.factory.annotation.Autowired;

public class ProjectBuildersExecutor {

@@ -36,11 +37,13 @@ public class ProjectBuildersExecutor {
private final GlobalConfiguration globalConfig;
private final ProjectBuilder[] projectBuilders;

@Autowired(required = false)
public ProjectBuildersExecutor(GlobalConfiguration globalConfig, ProjectBuilder... projectBuilders) {
this.globalConfig = globalConfig;
this.projectBuilders = projectBuilders;
}

@Autowired(required = false)
public ProjectBuildersExecutor(GlobalConfiguration globalConfig) {
this(globalConfig, new ProjectBuilder[0]);
}

+ 1
- 3
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectConfiguration.java 查看文件

@@ -20,14 +20,12 @@
package org.sonar.scanner.scan;

import java.util.Map;
import org.sonar.api.config.internal.Encryption;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.internal.Encryption;
import org.sonar.scanner.config.DefaultConfiguration;

public class ProjectConfiguration extends DefaultConfiguration {

public ProjectConfiguration(PropertyDefinitions propertyDefinitions, Encryption encryption, Map<String, String> props) {
super(propertyDefinitions, encryption, props);
}

}

+ 10
- 15
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectConfigurationProvider.java 查看文件

@@ -21,27 +21,22 @@ package org.sonar.scanner.scan;

import java.util.LinkedHashMap;
import java.util.Map;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.scanner.bootstrap.GlobalConfiguration;
import org.sonar.scanner.bootstrap.GlobalServerSettings;
import org.sonar.api.batch.fs.internal.DefaultInputProject;

public class ProjectConfigurationProvider extends ProviderAdapter {

private ProjectConfiguration projectConfig;
import org.springframework.context.annotation.Bean;

public class ProjectConfigurationProvider {
@Bean("ProjectConfiguration")
public ProjectConfiguration provide(DefaultInputProject project, GlobalConfiguration globalConfig, GlobalServerSettings globalServerSettings,
ProjectServerSettings projectServerSettings, MutableProjectSettings projectSettings) {
if (projectConfig == null) {

Map<String, String> settings = new LinkedHashMap<>();
settings.putAll(globalServerSettings.properties());
settings.putAll(projectServerSettings.properties());
settings.putAll(project.properties());
Map<String, String> settings = new LinkedHashMap<>();
settings.putAll(globalServerSettings.properties());
settings.putAll(projectServerSettings.properties());
settings.putAll(project.properties());

projectConfig = new ProjectConfiguration(globalConfig.getDefinitions(), globalConfig.getEncryption(), settings);
projectSettings.complete(projectConfig);
}
ProjectConfiguration projectConfig = new ProjectConfiguration(globalConfig.getDefinitions(), globalConfig.getEncryption(), settings);
projectSettings.complete(projectConfig);
return projectConfig;
}
}

+ 1
- 1
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectLock.java 查看文件

@@ -23,7 +23,7 @@ import java.io.IOException;
import java.nio.channels.OverlappingFileLockException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.picocontainer.Startable;
import org.sonar.api.Startable;
import org.sonar.api.batch.fs.internal.AbstractProjectOrModule;

public class ProjectLock implements Startable {

+ 3
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorValidator.java 查看文件

@@ -29,6 +29,7 @@ import org.sonar.api.utils.MessageException;
import org.sonar.core.component.ComponentKeys;
import org.sonar.scanner.bootstrap.GlobalConfiguration;
import org.sonar.scanner.scan.branch.BranchParamsValidator;
import org.springframework.beans.factory.annotation.Autowired;

import static java.lang.String.format;
import static java.util.Objects.nonNull;
@@ -52,11 +53,13 @@ public class ProjectReactorValidator {
@Nullable
private final BranchParamsValidator branchParamsValidator;

@Autowired(required = false)
public ProjectReactorValidator(GlobalConfiguration settings, @Nullable BranchParamsValidator branchParamsValidator) {
this.settings = settings;
this.branchParamsValidator = branchParamsValidator;
}

@Autowired(required = false)
public ProjectReactorValidator(GlobalConfiguration settings) {
this(settings, null);
}

+ 8
- 12
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectServerSettingsProvider.java 查看文件

@@ -21,14 +21,14 @@ package org.sonar.scanner.scan;

import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.CoreProperties;
import org.sonar.api.notifications.AnalysisWarnings;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.scanner.repository.settings.ProjectSettingsLoader;
import org.springframework.context.annotation.Bean;

public class ProjectServerSettingsProvider extends ProviderAdapter {
public class ProjectServerSettingsProvider {

private static final Logger LOG = Loggers.get(ProjectConfigurationProvider.class);

@@ -37,17 +37,13 @@ public class ProjectServerSettingsProvider extends ProviderAdapter {
"Archived Sub-Projects Settings' at project level, and clear the property to prevent the analysis from " +
"displaying this warning.";

private ProjectServerSettings singleton = null;

@Bean("ProjectServerSettings")
public ProjectServerSettings provide(ProjectSettingsLoader loader, AnalysisWarnings analysisWarnings) {
if (singleton == null) {
Map<String, String> serverSideSettings = loader.loadProjectSettings();
if (StringUtils.isNotBlank(serverSideSettings.get(CoreProperties.MODULE_LEVEL_ARCHIVED_SETTINGS))) {
LOG.warn(MODULE_LEVEL_ARCHIVED_SETTINGS_WARNING);
analysisWarnings.addUnique(MODULE_LEVEL_ARCHIVED_SETTINGS_WARNING);
}
singleton = new ProjectServerSettings(serverSideSettings);
Map<String, String> serverSideSettings = loader.loadProjectSettings();
if (StringUtils.isNotBlank(serverSideSettings.get(CoreProperties.MODULE_LEVEL_ARCHIVED_SETTINGS))) {
LOG.warn(MODULE_LEVEL_ARCHIVED_SETTINGS_WARNING);
analysisWarnings.addUnique(MODULE_LEVEL_ARCHIVED_SETTINGS_WARNING);
}
return singleton;
return new ProjectServerSettings(serverSideSettings);
}
}

sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java → sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringModuleScanContainer.java 查看文件

@@ -19,10 +19,11 @@
*/
package org.sonar.scanner.scan;

import javax.annotation.Priority;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.scan.filesystem.FileExclusions;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.scanner.bootstrap.ExtensionInstaller;
import org.sonar.scanner.bootstrap.SpringComponentContainer;
import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem;
import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore;
import org.sonar.scanner.sensor.ModuleSensorContext;
@@ -34,10 +35,11 @@ import static org.sonar.api.batch.InstantiationStrategy.PER_PROJECT;
import static org.sonar.scanner.bootstrap.ExtensionUtils.isDeprecatedScannerSide;
import static org.sonar.scanner.bootstrap.ExtensionUtils.isInstantiationStrategy;

public class ModuleScanContainer extends ComponentContainer {
@Priority(1)
public class SpringModuleScanContainer extends SpringComponentContainer {
private final DefaultInputModule module;

public ModuleScanContainer(ProjectScanContainer parent, DefaultInputModule module) {
public SpringModuleScanContainer(SpringComponentContainer parent, DefaultInputModule module) {
super(parent);
this.module = module;
}
@@ -70,7 +72,7 @@ public class ModuleScanContainer extends ComponentContainer {
}

private void addExtensions() {
ExtensionInstaller pluginInstaller = getComponentByType(ExtensionInstaller.class);
ExtensionInstaller pluginInstaller = parent.getComponentByType(ExtensionInstaller.class);
pluginInstaller.install(this, e -> isDeprecatedScannerSide(e) && isInstantiationStrategy(e, PER_PROJECT));
}

@@ -78,5 +80,4 @@ public class ModuleScanContainer extends ComponentContainer {
protected void doAfterStart() {
getComponentByType(ModuleSensorsExecutor.class).execute();
}

}

sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java → sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java 查看文件

@@ -20,12 +20,12 @@
package org.sonar.scanner.scan;

import javax.annotation.Nullable;
import javax.annotation.Priority;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.batch.fs.internal.SensorStrategy;
import org.sonar.api.batch.rule.CheckFactory;
import org.sonar.api.batch.sensor.issue.internal.DefaultNoSonarFilter;
import org.sonar.api.resources.Languages;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.MessageException;
@@ -34,7 +34,6 @@ import org.sonar.api.utils.log.Loggers;
import org.sonar.core.config.ScannerProperties;
import org.sonar.core.extension.CoreExtensionsInstaller;
import org.sonar.core.metric.ScannerMetrics;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.scanner.DefaultFileLinesContextFactory;
import org.sonar.scanner.ProjectInfo;
import org.sonar.scanner.analysis.AnalysisTempFolderProvider;
@@ -42,6 +41,7 @@ import org.sonar.scanner.bootstrap.ExtensionInstaller;
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.scanner.ci.CiConfigurationProvider;
import org.sonar.scanner.ci.vendors.AppVeyor;
import org.sonar.scanner.ci.vendors.AwsCodeBuild;
@@ -89,20 +89,15 @@ import org.sonar.scanner.report.TestExecutionPublisher;
import org.sonar.scanner.repository.ContextPropertiesCache;
import org.sonar.scanner.repository.DefaultProjectRepositoriesLoader;
import org.sonar.scanner.repository.DefaultQualityProfileLoader;
import org.sonar.scanner.repository.ReferenceBranchSupplier;
import org.sonar.scanner.repository.ProjectRepositoriesLoader;
import org.sonar.scanner.repository.ProjectRepositoriesSupplier;
import org.sonar.scanner.repository.QualityProfileLoader;
import org.sonar.scanner.repository.QualityProfilesProvider;
import org.sonar.scanner.repository.ReferenceBranchSupplier;
import org.sonar.scanner.repository.language.DefaultLanguagesRepository;
import org.sonar.scanner.repository.settings.DefaultProjectSettingsLoader;
import org.sonar.scanner.repository.settings.ProjectSettingsLoader;
import org.sonar.scanner.rule.ActiveRulesLoader;
import org.sonar.scanner.rule.ActiveRulesProvider;
import org.sonar.scanner.rule.DefaultActiveRulesLoader;
import org.sonar.scanner.rule.DefaultRulesLoader;
import org.sonar.scanner.rule.QProfileVerifier;
import org.sonar.scanner.rule.RulesLoader;
import org.sonar.scanner.rule.RulesProvider;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.scan.branch.BranchConfigurationProvider;
@@ -138,11 +133,11 @@ import static org.sonar.scanner.bootstrap.ExtensionUtils.isDeprecatedScannerSide
import static org.sonar.scanner.bootstrap.ExtensionUtils.isInstantiationStrategy;
import static org.sonar.scanner.bootstrap.ExtensionUtils.isScannerSide;

public class ProjectScanContainer extends ComponentContainer {
private static final Logger LOG = Loggers.get(ProjectScanContainer.class);
@Priority(2)
public class SpringProjectScanContainer extends SpringComponentContainer {
private static final Logger LOG = Loggers.get(SpringProjectScanContainer.class);

public ProjectScanContainer(ComponentContainer globalContainer) {
public SpringProjectScanContainer(SpringComponentContainer globalContainer) {
super(globalContainer);
}

@@ -150,9 +145,6 @@ public class ProjectScanContainer extends ComponentContainer {
protected void doBeforeStart() {
addScannerExtensions();
addScannerComponents();
ProjectLock lock = getComponentByType(ProjectLock.class);
lock.tryLock();
getComponentByType(WorkDirectoriesInitializer.class).execute();
}

private void addScannerComponents() {
@@ -207,7 +199,7 @@ public class ProjectScanContainer extends ComponentContainer {
DefaultMetricFinder.class,

// lang
Languages.class,
LanguagesProvider.class,
DefaultLanguagesRepository.class,

// issue exclusions
@@ -298,17 +290,17 @@ public class ProjectScanContainer extends ComponentContainer {
add(GitScmSupport.getObjects());
add(SvnScmSupport.getObjects());

addIfMissing(DefaultProjectSettingsLoader.class, ProjectSettingsLoader.class);
addIfMissing(DefaultRulesLoader.class, RulesLoader.class);
addIfMissing(DefaultActiveRulesLoader.class, ActiveRulesLoader.class);
addIfMissing(DefaultQualityProfileLoader.class, QualityProfileLoader.class);
addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class);
add(DefaultProjectSettingsLoader.class,
DefaultRulesLoader.class,
DefaultActiveRulesLoader.class,
DefaultQualityProfileLoader.class,
DefaultProjectRepositoriesLoader.class);
}

private void addScannerExtensions() {
getComponentByType(CoreExtensionsInstaller.class)
getParent().getComponentByType(CoreExtensionsInstaller.class)
.install(this, noExtensionFilter(), extension -> getScannerProjectExtensionsFilter().accept(extension));
getComponentByType(ExtensionInstaller.class)
getParent().getComponentByType(ExtensionInstaller.class)
.install(this, getScannerProjectExtensionsFilter());
}

@@ -323,6 +315,7 @@ public class ProjectScanContainer extends ComponentContainer {

@Override
protected void doAfterStart() {
getComponentByType(ProjectLock.class).tryLock();
GlobalAnalysisMode analysisMode = getComponentByType(GlobalAnalysisMode.class);
InputModuleHierarchy tree = getComponentByType(InputModuleHierarchy.class);
ScanProperties properties = getComponentByType(ScanProperties.class);
@@ -381,7 +374,7 @@ public class ProjectScanContainer extends ComponentContainer {
}

void scan(DefaultInputModule module) {
new ModuleScanContainer(this, module).execute();
new SpringModuleScanContainer(this, module).execute();
}

}

+ 7
- 14
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/WorkDirectoriesInitializer.java 查看文件

@@ -33,30 +33,23 @@ import org.sonar.scanner.fs.InputModuleHierarchy;
* Be careful that sub module work dir might be nested in parent working directory.
*/
public class WorkDirectoriesInitializer {

private InputModuleHierarchy moduleHierarchy;

public WorkDirectoriesInitializer(InputModuleHierarchy moduleHierarchy) {
this.moduleHierarchy = moduleHierarchy;
}

public void execute() {
cleanAllWorkingDirs(moduleHierarchy.root());
mkdirsAllWorkingDirs(moduleHierarchy.root());
public void execute(InputModuleHierarchy moduleHierarchy) {
cleanAllWorkingDirs(moduleHierarchy, moduleHierarchy.root());
mkdirsAllWorkingDirs(moduleHierarchy, moduleHierarchy.root());
}

private void cleanAllWorkingDirs(DefaultInputModule module) {
private static void cleanAllWorkingDirs(InputModuleHierarchy moduleHierarchy, DefaultInputModule module) {
for (DefaultInputModule sub : moduleHierarchy.children(module)) {
cleanAllWorkingDirs(sub);
cleanAllWorkingDirs(moduleHierarchy, sub);
}
if (Files.exists(module.getWorkDir())) {
deleteAllRecursivelyExceptLockFile(module.getWorkDir());
}
}

private void mkdirsAllWorkingDirs(DefaultInputModule module) {
private static void mkdirsAllWorkingDirs(InputModuleHierarchy moduleHierarchy, DefaultInputModule module) {
for (DefaultInputModule sub : moduleHierarchy.children(module)) {
mkdirsAllWorkingDirs(sub);
mkdirsAllWorkingDirs(moduleHierarchy, sub);
}
try {
Files.createDirectories(module.getWorkDir());

+ 11
- 14
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/BranchConfigurationProvider.java 查看文件

@@ -19,31 +19,28 @@
*/
package org.sonar.scanner.scan.branch;

import org.picocontainer.annotations.Nullable;
import org.picocontainer.injectors.ProviderAdapter;
import javax.annotation.Nullable;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.scanner.scan.ProjectConfiguration;
import org.springframework.context.annotation.Bean;

public class BranchConfigurationProvider extends ProviderAdapter {
public class BranchConfigurationProvider {

private static final Logger LOG = Loggers.get(BranchConfigurationProvider.class);
private static final String LOG_MSG = "Load branch configuration";

private BranchConfiguration branchConfiguration = null;

@Bean("BranchConfiguration")
public BranchConfiguration provide(@Nullable BranchConfigurationLoader loader, ProjectConfiguration projectConfiguration,
ProjectBranches branches, ProjectPullRequests pullRequests) {
if (branchConfiguration == null) {
if (loader == null) {
branchConfiguration = new DefaultBranchConfiguration();
} else {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
branchConfiguration = loader.load(projectConfiguration.getProperties(), branches, pullRequests);
profiler.stopInfo();
}
if (loader == null) {
return new DefaultBranchConfiguration();
} else {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
BranchConfiguration branchConfiguration = loader.load(projectConfiguration.getProperties(), branches, pullRequests);
profiler.stopInfo();
return branchConfiguration;
}
return branchConfiguration;
}
}

+ 7
- 13
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/ProjectBranchesProvider.java 查看文件

@@ -20,33 +20,27 @@
package org.sonar.scanner.scan.branch;

import java.util.Collections;
import org.picocontainer.annotations.Nullable;
import org.picocontainer.injectors.ProviderAdapter;
import javax.annotation.Nullable;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.scanner.bootstrap.ScannerProperties;
import org.springframework.context.annotation.Bean;

public class ProjectBranchesProvider extends ProviderAdapter {
public class ProjectBranchesProvider {

private static final Logger LOG = Loggers.get(ProjectBranchesProvider.class);
private static final String LOG_MSG = "Load project branches";

private ProjectBranches branches = null;

@Bean("ProjectBranches")
public ProjectBranches provide(@Nullable ProjectBranchesLoader loader, ScannerProperties scannerProperties) {
if (this.branches != null) {
return this.branches;
}

if (loader == null) {
this.branches = new ProjectBranches(Collections.emptyList());
return this.branches;
return new ProjectBranches(Collections.emptyList());
}

Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
this.branches = loader.load(scannerProperties.getProjectKey());
ProjectBranches branches = loader.load(scannerProperties.getProjectKey());
profiler.stopInfo();
return this.branches;
return branches;
}
}

+ 7
- 12
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/ProjectPullRequestsProvider.java 查看文件

@@ -20,31 +20,26 @@
package org.sonar.scanner.scan.branch;

import java.util.Collections;
import org.picocontainer.injectors.ProviderAdapter;
import javax.annotation.Nullable;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.scanner.bootstrap.ScannerProperties;
import org.springframework.context.annotation.Bean;

public class ProjectPullRequestsProvider extends ProviderAdapter {
public class ProjectPullRequestsProvider {

private static final Logger LOG = Loggers.get(ProjectPullRequestsProvider.class);
private static final String LOG_MSG = "Load project pull requests";

private ProjectPullRequests pullRequests = null;

public ProjectPullRequests provide(@org.picocontainer.annotations.Nullable ProjectPullRequestsLoader loader, ScannerProperties scannerProperties) {
if (pullRequests != null) {
return pullRequests;
}

@Bean("ProjectPullRequests")
public ProjectPullRequests provide(@Nullable ProjectPullRequestsLoader loader, ScannerProperties scannerProperties) {
if (loader == null) {
pullRequests = new ProjectPullRequests(Collections.emptyList());
return pullRequests;
return new ProjectPullRequests(Collections.emptyList());
}

Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
pullRequests = loader.load(scannerProperties.getProjectKey());
ProjectPullRequests pullRequests = loader.load(scannerProperties.getProjectKey());
profiler.stopInfo();
return pullRequests;
}

+ 5
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultModuleFileSystem.java 查看文件

@@ -22,8 +22,13 @@ package org.sonar.scanner.scan.filesystem;
import org.sonar.api.batch.fs.internal.DefaultInputModule;
import org.sonar.api.batch.fs.internal.predicates.DefaultFilePredicates;

import javax.annotation.Priority;
import javax.inject.Inject;

@Priority(1)
public class DefaultModuleFileSystem extends MutableFileSystem {

@Inject
public DefaultModuleFileSystem(ModuleInputComponentStore moduleInputFileCache, DefaultInputModule module) {
super(module.getBaseDir(), moduleInputFileCache, new DefaultFilePredicates(module.getBaseDir()));
initFields(module);

+ 5
- 0
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultProjectFileSystem.java 查看文件

@@ -22,8 +22,13 @@ package org.sonar.scanner.scan.filesystem;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.fs.internal.predicates.DefaultFilePredicates;

import javax.annotation.Priority;
import javax.inject.Inject;

@Priority(2)
public class DefaultProjectFileSystem extends MutableFileSystem {

@Inject
public DefaultProjectFileSystem(InputComponentStore inputComponentStore, DefaultInputProject project) {
super(project.getBaseDir(), inputComponentStore, new DefaultFilePredicates(project.getBaseDir()));
setFields(project);

+ 0
- 8
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java 查看文件

@@ -90,14 +90,6 @@ public class FileIndexer {
this.projectExclusionFilters = projectExclusionFilters;
}

public FileIndexer(DefaultInputProject project, ScannerComponentIdGenerator scannerComponentIdGenerator, InputComponentStore componentStore,
ProjectExclusionFilters projectExclusionFilters, ProjectCoverageAndDuplicationExclusions projectCoverageAndDuplicationExclusions,
IssueExclusionsLoader issueExclusionsLoader, MetadataGenerator metadataGenerator, SensorStrategy sensorStrategy,
LanguageDetection languageDetection, AnalysisWarnings analysisWarnings, ScanProperties properties) {
this(project, scannerComponentIdGenerator, componentStore, projectExclusionFilters, projectCoverageAndDuplicationExclusions, issueExclusionsLoader,
metadataGenerator, sensorStrategy, languageDetection, analysisWarnings, properties, new InputFileFilter[0]);
}

void indexFile(DefaultInputModule module, ModuleExclusionFilters moduleExclusionFilters, ModuleCoverageAndDuplicationExclusions moduleCoverageAndDuplicationExclusions,
Path sourceFile, Type type, ProgressReport progressReport, ProjectFileIndexer.ExclusionCounter exclusionCounter, @Nullable IgnoreCommand ignoreCommand)
throws IOException {

+ 6
- 10
sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFilesProvider.java 查看文件

@@ -22,29 +22,25 @@ package org.sonar.scanner.scm;
import java.nio.file.Path;
import java.util.Collection;
import javax.annotation.CheckForNull;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.batch.scm.ScmProvider;
import org.sonar.api.impl.utils.ScannerUtils;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.api.impl.utils.ScannerUtils;
import org.springframework.context.annotation.Bean;

public class ScmChangedFilesProvider extends ProviderAdapter {
public class ScmChangedFilesProvider {
private static final Logger LOG = Loggers.get(ScmChangedFilesProvider.class);
private static final String LOG_MSG = "SCM collecting changed files in the branch";

private ScmChangedFiles scmBranchChangedFiles;

@Bean("ScmChangedFiles")
public ScmChangedFiles provide(ScmConfiguration scmConfiguration, BranchConfiguration branchConfiguration, DefaultInputProject project) {
if (scmBranchChangedFiles == null) {
Path rootBaseDir = project.getBaseDir();
Collection<Path> changedFiles = loadChangedFilesIfNeeded(scmConfiguration, branchConfiguration, rootBaseDir);
validatePaths(changedFiles);
scmBranchChangedFiles = new ScmChangedFiles(changedFiles);
}
return scmBranchChangedFiles;
return new ScmChangedFiles(changedFiles);
}

private static void validatePaths(@javax.annotation.Nullable Collection<Path> paths) {

+ 3
- 6
sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java 查看文件

@@ -24,11 +24,11 @@ import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import org.apache.commons.lang.StringUtils;
import org.picocontainer.Startable;
import org.sonar.api.CoreProperties;
import org.sonar.api.Properties;
import org.sonar.api.Property;
import org.sonar.api.PropertyType;
import org.sonar.api.Startable;
import org.sonar.api.batch.scm.ScmProvider;
import org.sonar.api.config.Configuration;
import org.sonar.api.notifications.AnalysisWarnings;
@@ -67,7 +67,8 @@ public class ScmConfiguration implements Startable {

private ScmProvider provider;

public ScmConfiguration(InputModuleHierarchy moduleHierarchy, Configuration settings, AnalysisWarnings analysisWarnings, ScmProvider... providers) {
public ScmConfiguration(InputModuleHierarchy moduleHierarchy, Configuration settings, AnalysisWarnings analysisWarnings,
ScmProvider... providers) {
this.moduleHierarchy = moduleHierarchy;
this.settings = settings;
this.analysisWarnings = analysisWarnings;
@@ -76,10 +77,6 @@ public class ScmConfiguration implements Startable {
}
}

public ScmConfiguration(InputModuleHierarchy moduleHierarchy, Configuration settings, AnalysisWarnings analysisWarnings) {
this(moduleHierarchy, settings, analysisWarnings, new ScmProvider[0]);
}

@Override
public void start() {
if (isDisabled()) {

+ 2
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorContext.java 查看文件

@@ -34,9 +34,9 @@ public class ModuleSensorContext extends ProjectSensorContext {

private final InputModule module;

public ModuleSensorContext(DefaultInputProject project, InputModule module, Configuration config, Settings mutableSettings, FileSystem fs, ActiveRules activeRules,
public ModuleSensorContext(DefaultInputProject project, InputModule module, Configuration config, Settings mutableModuleSettings, FileSystem fs, ActiveRules activeRules,
SensorStorage sensorStorage, SonarRuntime sonarRuntime) {
super(project, config, mutableSettings, fs, activeRules, sensorStorage, sonarRuntime);
super(project, config, mutableModuleSettings, fs, activeRules, sensorStorage, sonarRuntime);
this.module = module;
}


+ 2
- 1
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorExtensionDictionary.java 查看文件

@@ -24,6 +24,7 @@ import java.util.stream.Collectors;
import org.sonar.api.batch.sensor.Sensor;
import org.sonar.core.platform.ComponentContainer;
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;

@@ -34,7 +35,7 @@ public class ModuleSensorExtensionDictionary extends AbstractExtensionDictionary
private final MutableFileSystem fileSystem;
private final BranchConfiguration branchConfiguration;

public ModuleSensorExtensionDictionary(ComponentContainer componentContainer, ModuleSensorContext sensorContext, ModuleSensorOptimizer sensorOptimizer,
public ModuleSensorExtensionDictionary(SpringComponentContainer componentContainer, ModuleSensorContext sensorContext, ModuleSensorOptimizer sensorOptimizer,
MutableFileSystem fileSystem, BranchConfiguration branchConfiguration) {
super(componentContainer);
this.sensorContext = sensorContext;

+ 2
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorExtensionDictionary.java 查看文件

@@ -23,8 +23,8 @@ import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.sonar.api.scanner.sensor.ProjectSensor;
import org.sonar.core.platform.ComponentContainer;
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;

@@ -35,7 +35,7 @@ public class ProjectSensorExtensionDictionary extends AbstractExtensionDictionar
private final MutableFileSystem fileSystem;
private final BranchConfiguration branchConfiguration;

public ProjectSensorExtensionDictionary(ComponentContainer componentContainer, ProjectSensorContext sensorContext, ProjectSensorOptimizer sensorOptimizer,
public ProjectSensorExtensionDictionary(SpringComponentContainer componentContainer, ProjectSensorContext sensorContext, ProjectSensorOptimizer sensorOptimizer,
MutableFileSystem fileSystem, BranchConfiguration branchConfiguration) {
super(componentContainer);
this.sensorContext = sensorContext;

+ 9
- 3
sonar-scanner-engine/src/main/resources/org/sonar/batch/bootstrapper/logback.xml 查看文件

@@ -28,6 +28,15 @@
<level value="INFO"/>
</logger>

<!-- Spring generates too many DEBUG logs when sonar.verbose is set -->
<logger name="org.springframework">
<level value="INFO"/>
</logger>

<logger name="org.sonar.scanner.bootstrap.PriorityBeanFactory">
<level value="INFO"/>
</logger>

<!-- sonar.showSql -->
<!-- see also org.sonar.db.MyBatis#configureLogback() -->
<logger name="org.mybatis">
@@ -42,9 +51,6 @@
<logger name="java.sql.ResultSet">
<level value="WARN"/>
</logger>
<logger name="PERSISTIT">
<level value="WARN"/>
</logger>

<root>
<!-- sonar.verbose -->

+ 0
- 4
sonar-scanner-engine/src/main/resources/org/sonar/batch/logback.xml 查看文件

@@ -19,10 +19,6 @@
<level value="WARN"/>
</logger>

<logger name="PERSISTIT">
<level value="WARN"/>
</logger>

<root>
<!-- sonar.verbose -->
<level value="${ROOT_LOGGER_LEVEL}"/>

+ 0
- 85
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalContainerTest.java 查看文件

@@ -1,85 +0,0 @@
/*
* 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.ImmutableMap;
import com.google.common.collect.Lists;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.ScannerSide;
import org.sonar.api.utils.TempFolder;
import org.sonar.batch.bootstrapper.EnvironmentInformation;
import org.sonar.core.util.UuidFactory;

import static org.assertj.core.api.Assertions.assertThat;

public class GlobalContainerTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();

private GlobalContainer createContainer(List<Object> extensions) {
Map<String, String> props = ImmutableMap.of(CoreProperties.WORKING_DIRECTORY, temp.getRoot().getAbsolutePath(),
CoreProperties.GLOBAL_WORKING_DIRECTORY, temp.getRoot().getAbsolutePath());

GlobalContainer container = GlobalContainer.create(props, extensions);
container.doBeforeStart();
return container;
}

@Test
public void should_add_components() {
GlobalContainer container = createContainer(Collections.singletonList(new EnvironmentInformation("maven", "3.1.0")));

assertThat(container.getComponentByType(UuidFactory.class)).isNotNull();
assertThat(container.getComponentByType(TempFolder.class)).isNotNull();
}

@Test
public void should_add_bootstrap_extensions() {
GlobalContainer container = createContainer(Lists.newArrayList(Foo.class, new Bar()));

assertThat(container.getComponentByType(Foo.class)).isNotNull();
assertThat(container.getComponentByType(Bar.class)).isNotNull();
}

@Test
public void shouldFormatTime() {
assertThat(GlobalContainer.formatTime(1 * 60 * 60 * 1000 + 2 * 60 * 1000 + 3 * 1000 + 400)).isEqualTo("1:02:03.400 s");
assertThat(GlobalContainer.formatTime(2 * 60 * 1000 + 3 * 1000 + 400)).isEqualTo("2:03.400 s");
assertThat(GlobalContainer.formatTime(3 * 1000 + 400)).isEqualTo("3.400 s");
assertThat(GlobalContainer.formatTime(400)).isEqualTo("0.400 s");
}

@ScannerSide
public static class Foo {

}

@ScannerSide
public static class Bar {

}

}

+ 41
- 0
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/LazyBeanFactoryPostProcessorTest.java 查看文件

@@ -0,0 +1,41 @@
/*
* 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();
}

}

+ 26
- 14
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ModuleSensorExtensionDictionaryTest.java 查看文件

@@ -20,9 +20,6 @@
package org.sonar.scanner.bootstrap;

import com.google.common.collect.Lists;
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;
@@ -30,11 +27,13 @@ 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.core.platform.ComponentContainer;
import org.sonar.scanner.scan.SpringModuleScanContainer;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.scan.filesystem.MutableFileSystem;
import org.sonar.scanner.sensor.ModuleSensorContext;
@@ -42,6 +41,10 @@ import org.sonar.scanner.sensor.ModuleSensorExtensionDictionary;
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;
@@ -59,10 +62,16 @@ public class ModuleSensorExtensionDictionaryTest {
}

private ModuleSensorExtensionDictionary newSelector(Object... extensions) {
ComponentContainer iocContainer = new ComponentContainer();
for (Object extension : extensions) {
iocContainer.addSingleton(extension);
}
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();

return new ModuleSensorExtensionDictionary(iocContainer, mock(ModuleSensorContext.class), sensorOptimizer, fileSystem, branchConfiguration);
}

@@ -95,14 +104,17 @@ public class ModuleSensorExtensionDictionaryTest {
Sensor b = new FakeSensor();
Sensor c = new FakeSensor();

ComponentContainer grandParent = new ComponentContainer();
grandParent.addSingleton(a);
SpringComponentContainer grandParent = new SpringComponentContainer();
grandParent.add(a);
grandParent.context.refresh();

ComponentContainer parent = grandParent.createChild();
parent.addSingleton(b);
SpringComponentContainer parent = grandParent.createChild();
parent.add(b);
parent.context.refresh();

ComponentContainer child = parent.createChild();
child.addSingleton(c);
SpringComponentContainer child = parent.createChild();
child.add(c);
child.context.refresh();

ModuleSensorExtensionDictionary dictionnary = new ModuleSensorExtensionDictionary(child, mock(ModuleSensorContext.class), mock(ModuleSensorOptimizer.class),
fileSystem, branchConfiguration);

+ 103
- 0
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PriorityBeanFactoryTest.java 查看文件

@@ -0,0 +1,103 @@
/*
* 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 {

}

}

+ 0
- 10
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java 查看文件

@@ -66,14 +66,4 @@ public class ScannerWsClientProviderTest {
assertThat(httpConnector.baseUrl()).isEqualTo("https://here/sonarqube/");
assertThat(httpConnector.okHttpClient().proxy()).isNull();
}

@Test
public void build_singleton() {
System2 system = mock(System2.class);

ScannerProperties settings = new ScannerProperties(new HashMap<>());
DefaultScannerWsClient first = underTest.provide(settings, env, new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())), system);
DefaultScannerWsClient second = underTest.provide(settings, env, new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())), system);
assertThat(first).isSameAs(second);
}
}

+ 213
- 0
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringComponentContainerTest.java 查看文件

@@ -0,0 +1,213 @@
/*
* 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("org.sonar.scanner.bootstrap.SpringComponentContainerTest.ToString-a", "org.sonar.scanner.bootstrap.SpringComponentContainerTest.ToString-b");
assertThat(container.getComponentsByType(ToString.class)).hasSize(2);
}

@Test
public void register_class_with_fqcn() {
SpringComponentContainer container = new SimpleContainer(A.class, B.class);
container.startComponents();
assertThat(container.context.getBeanDefinitionNames())
.contains("org.sonar.scanner.bootstrap.SpringComponentContainerTest$A", "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);
}
}
}

+ 34
- 0
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringGlobalContainerTest.java 查看文件

@@ -0,0 +1,34 @@
/*
* 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 static org.assertj.core.api.Assertions.assertThat;

public class SpringGlobalContainerTest {
@Test
public void shouldFormatTime() {
assertThat(SpringGlobalContainer.formatTime(1 * 60 * 60 * 1000 + 2 * 60 * 1000 + 3 * 1000 + 400)).isEqualTo("1:02:03.400 s");
assertThat(SpringGlobalContainer.formatTime(2 * 60 * 1000 + 3 * 1000 + 400)).isEqualTo("2:03.400 s");
assertThat(SpringGlobalContainer.formatTime(3 * 1000 + 400)).isEqualTo("3.400 s");
assertThat(SpringGlobalContainer.formatTime(400)).isEqualTo("0.400 s");
}
}

+ 64
- 0
sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/StartableBeanPostProcessorTest.java 查看文件

@@ -0,0 +1,64 @@
/*
* 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);
}

}

+ 19
- 2
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java 查看文件

@@ -36,6 +36,7 @@ import java.util.Map;
import java.util.Properties;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.Priority;
import org.apache.commons.io.FileUtils;
import org.junit.rules.ExternalResource;
import org.sonar.api.Plugin;
@@ -100,7 +101,7 @@ public class ScannerMediumTester extends ExternalResource {
private final FakeQualityProfileLoader qualityProfiles = new FakeQualityProfileLoader();
private final FakeActiveRulesLoader activeRules = new FakeActiveRulesLoader();
private final FakeSonarRuntime sonarRuntime = new FakeSonarRuntime();
private final CeTaskReportDataHolder reportMetadataHolder = new CeTaskReportDataHolder();
private final CeTaskReportDataHolder reportMetadataHolder = new CeTaskReportDataHolderExt();
private LogOutput logOutput = null;

private static void createWorkingDirs() throws IOException {
@@ -280,7 +281,7 @@ public class ScannerMediumTester extends ExternalResource {

public static class AnalysisBuilder {
private final Map<String, String> taskProperties = new HashMap<>();
private ScannerMediumTester tester;
private final ScannerMediumTester tester;

public AnalysisBuilder(ScannerMediumTester tester) {
this.tester = tester;
@@ -327,6 +328,7 @@ public class ScannerMediumTester extends ExternalResource {

}

@Priority(1)
private static class FakeRulesLoader implements RulesLoader {
private List<org.sonarqube.ws.Rules.ListResponse.Rule> rules = new LinkedList<>();

@@ -341,6 +343,7 @@ public class ScannerMediumTester extends ExternalResource {
}
}

@Priority(1)
private static class FakeActiveRulesLoader implements ActiveRulesLoader {
private List<LoadedActiveRule> activeRules = new LinkedList<>();

@@ -354,6 +357,7 @@ public class ScannerMediumTester extends ExternalResource {
}
}

@Priority(1)
private static class FakeMetricsRepositoryLoader implements MetricsRepositoryLoader {

private int metricId = 1;
@@ -374,6 +378,7 @@ public class ScannerMediumTester extends ExternalResource {

}

@Priority(1)
private static class FakeProjectRepositoriesLoader implements ProjectRepositoriesLoader {
private Map<String, FileData> fileDataMap = new HashMap<>();

@@ -389,6 +394,7 @@ public class ScannerMediumTester extends ExternalResource {

}

@Priority(1)
private static class FakeBranchConfiguration implements BranchConfiguration {

private BranchType branchType = BranchType.BRANCH;
@@ -425,6 +431,7 @@ public class ScannerMediumTester extends ExternalResource {
}
}

@Priority(1)
private static class FakeSonarRuntime implements SonarRuntime {

private SonarEdition edition;
@@ -483,6 +490,7 @@ public class ScannerMediumTester extends ExternalResource {
return this;
}

@Priority(1)
private class FakeBranchConfigurationLoader implements BranchConfigurationLoader {
@Override
public BranchConfiguration load(Map<String, String> projectSettings, ProjectBranches branches, ProjectPullRequests pullRequests) {
@@ -490,6 +498,7 @@ public class ScannerMediumTester extends ExternalResource {
}
}

@Priority(1)
private static class FakeQualityProfileLoader implements QualityProfileLoader {

private List<QualityProfile> qualityProfiles = new LinkedList<>();
@@ -509,6 +518,7 @@ public class ScannerMediumTester extends ExternalResource {
}
}

@Priority(1)
private static class FakeGlobalSettingsLoader implements GlobalSettingsLoader {

private Map<String, String> globalSettings = new HashMap<>();
@@ -523,6 +533,7 @@ public class ScannerMediumTester extends ExternalResource {
}
}

@Priority(1)
private static class FakeNewCodePeriodLoader implements NewCodePeriodLoader {
private NewCodePeriods.ShowWSResponse response;

@@ -536,6 +547,7 @@ public class ScannerMediumTester extends ExternalResource {
}
}

@Priority(1)
private static class FakeProjectSettingsLoader implements ProjectSettingsLoader {

private Map<String, String> projectSettings = new HashMap<>();
@@ -550,4 +562,9 @@ public class ScannerMediumTester extends ExternalResource {
}
}

@Priority(1)
private static class CeTaskReportDataHolderExt extends CeTaskReportDataHolder {

}

}

+ 3
- 2
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/NoLanguagesPluginsMediumTest.java 查看文件

@@ -26,6 +26,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.scanner.mediumtest.ScannerMediumTester;
import org.springframework.beans.factory.UnsatisfiedDependencyException;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

@@ -43,8 +44,8 @@ public class NoLanguagesPluginsMediumTest {
assertThatThrownBy(() -> tester
.newAnalysis(new File(projectDir, "sonar-project.properties"))
.execute())
.isInstanceOf(IllegalStateException.class)
.hasMessage("No language plugins are installed.");
.isInstanceOf(UnsatisfiedDependencyException.class)
.hasRootCauseMessage("No language plugins are installed.");
}

private File copyProject(String path) throws Exception {

+ 8
- 6
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/issues/IssuesMediumTest.java 查看文件

@@ -73,11 +73,11 @@ public class IssuesMediumTest {

List<Issue> issues = result.issuesFor(result.inputFile("xources/hello/HelloJava.xoo"));
assertThat(issues).hasSize(8 /* lines */);
List<ExternalIssue> externalIssues = result.externalIssuesFor(result.inputFile("xources/hello/HelloJava.xoo"));
assertThat(externalIssues).isEmpty();
}
@Test
public void testOneExternalIssuePerLine() throws Exception {
File projectDir = new File("test-resources/mediumtest/xoo/sample");
@@ -243,7 +243,8 @@ public class IssuesMediumTest {
.build())
.execute();

assertThat(logTester.logs(LoggerLevel.WARN)).contains("Specifying module-relative paths at project level in property 'sonar.issue.ignore.multicriteria' is deprecated. To continue matching files like 'moduleA/src/sampleA.xoo', update this property so that patterns refer to project-relative paths.");
assertThat(logTester.logs(LoggerLevel.WARN)).contains(
"Specifying module-relative paths at project level in property 'sonar.issue.ignore.multicriteria' is deprecated. To continue matching files like 'moduleA/src/sampleA.xoo', update this property so that patterns refer to project-relative paths.");

List<Issue> issues = result.issuesFor(result.inputFile("moduleA/src/sampleA.xoo"));
assertThat(issues).isEmpty();
@@ -295,7 +296,8 @@ public class IssuesMediumTest {
.build())
.execute();

assertThat(logTester.logs(LoggerLevel.WARN)).containsOnly("Specifying issue exclusions at module level is not supported anymore. Configure the property 'sonar.issue.ignore.multicriteria' and any other issue exclusions at project level.");
assertThat(logTester.logs(LoggerLevel.WARN)).containsOnly(
"Specifying issue exclusions at module level is not supported anymore. Configure the property 'sonar.issue.ignore.multicriteria' and any other issue exclusions at project level.");

List<Issue> issues = result.issuesFor(result.inputFile("moduleA/src/sampleA.xoo"));
assertThat(issues).hasSize(10);
@@ -303,7 +305,6 @@ public class IssuesMediumTest {
issues = result.issuesFor(result.inputFile("moduleB/src/sampleB.xoo"));
assertThat(issues).hasSize(10);


// SONAR-11850 The Maven scanner replicates properties defined on the root module to all modules
logTester.clear();
result = tester.newAnalysis()
@@ -387,7 +388,8 @@ public class IssuesMediumTest {
.build())
.execute();

assertThat(logTester.logs(LoggerLevel.WARN)).contains("Specifying module-relative paths at project level in property 'sonar.issue.enforce.multicriteria' is deprecated. To continue matching files like 'moduleA/src/sampleA.xoo', update this property so that patterns refer to project-relative paths.");
assertThat(logTester.logs(LoggerLevel.WARN)).contains(
"Specifying module-relative paths at project level in property 'sonar.issue.enforce.multicriteria' is deprecated. To continue matching files like 'moduleA/src/sampleA.xoo', update this property so that patterns refer to project-relative paths.");

List<Issue> issues = result.issuesFor(result.inputFile("moduleA/src/sampleA.xoo"));
assertThat(issues).hasSize(10);

+ 5
- 3
sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/log/ExceptionHandlingMediumTest.java 查看文件

@@ -21,12 +21,14 @@ package org.sonar.scanner.mediumtest.log;

import java.util.Collections;
import java.util.Map;
import javax.annotation.Priority;
import org.junit.BeforeClass;
import org.junit.Test;
import org.sonar.api.utils.MessageException;
import org.sonar.batch.bootstrapper.Batch;
import org.sonar.batch.bootstrapper.EnvironmentInformation;
import org.sonar.scanner.repository.settings.GlobalSettingsLoader;
import org.springframework.beans.factory.UnsatisfiedDependencyException;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

@@ -78,12 +80,12 @@ public class ExceptionHandlingMediumTest {
@Test
public void testWithVerbose() {
setUp(true);

assertThatThrownBy(() -> batch.execute())
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("Unable to load component class");
.isInstanceOf(UnsatisfiedDependencyException.class)
.hasMessageContaining("Error loading settings");
}

@Priority(1)
private static class ErrorGlobalSettingsLoader implements GlobalSettingsLoader {
boolean withCause = false;


+ 5
- 5
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java 查看文件

@@ -25,6 +25,7 @@ import java.io.PipedOutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -77,8 +78,7 @@ public class ReportPublisherTest {
private AnalysisContextReportPublisher contextPublisher = mock(AnalysisContextReportPublisher.class);
private BranchConfiguration branchConfiguration = mock(BranchConfiguration.class);
private CeTaskReportDataHolder reportMetadataHolder = mock(CeTaskReportDataHolder.class);
private ReportPublisher underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, reportTempFolder,
new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder);
private ReportPublisher underTest;

@Before
public void setUp() {
@@ -90,6 +90,8 @@ public class ReportPublisherTest {
when(properties.metadataFilePath()).thenReturn(reportTempFolder.newDir().toPath()
.resolve("folder")
.resolve("report-task.txt"));
underTest = new ReportPublisher(properties, wsClient, server, contextPublisher, moduleHierarchy, mode, reportTempFolder,
new ReportPublisherStep[0], branchConfiguration, reportMetadataHolder);
}

@Test
@@ -109,7 +111,7 @@ public class ReportPublisherTest {
underTest.prepareAndDumpMetadata("TASK-123");

assertThat(readFileToString(properties.metadataFilePath().toFile(), StandardCharsets.UTF_8)).isEqualTo(
"projectKey=org.sonarsource.sonarqube:sonarqube\n" +
"projectKey=org.sonarsource.sonarqube:sonarqube\n" +
"serverUrl=https://localhost\n" +
"serverVersion=6.4\n" +
"dashboardUrl=https://localhost/dashboard?id=org.sonarsource.sonarqube%3Asonarqube\n" +
@@ -249,7 +251,6 @@ public class ReportPublisherTest {
public void should_not_delete_report_if_property_is_set() throws IOException {
when(properties.shouldKeepReport()).thenReturn(true);
Path reportDir = reportTempFolder.getRoot().toPath().resolve("scanner-report");
Files.createDirectory(reportDir);

underTest.start();
underTest.stop();
@@ -259,7 +260,6 @@ public class ReportPublisherTest {
@Test
public void should_delete_report_by_default() throws IOException {
Path reportDir = reportTempFolder.getRoot().toPath().resolve("scanner-report");
Files.createDirectory(reportDir);

underTest.start();
underTest.stop();

sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectScanContainerTest.java → sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/SpringProjectScanContainerTest.java 查看文件

@@ -27,11 +27,11 @@ import org.sonar.scanner.bootstrap.ExtensionMatcher;

import static org.assertj.core.api.Assertions.assertThat;

public class ProjectScanContainerTest {
public class SpringProjectScanContainerTest {

@Test
public void should_add_only_batch_extensions() {
ExtensionMatcher filter = ProjectScanContainer.getScannerProjectExtensionsFilter();
ExtensionMatcher filter = SpringProjectScanContainer.getScannerProjectExtensionsFilter();

assertThat(filter.accept(new MyBatchExtension())).isTrue();
assertThat(filter.accept(MyBatchExtension.class)).isTrue();

+ 0
- 0
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java 查看文件


部分文件因文件數量過多而無法顯示

Loading…
取消
儲存