diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2022-01-05 16:17:09 -0600 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-02-02 20:02:54 +0000 |
commit | a53007e8246c8d44b0c9af4bd3757313c48dd230 (patch) | |
tree | c53786ac80233b0296ee345e11d64bb762e5b463 | |
parent | e6afd7889c39e6b9db5e62ee5f850eae598ba62d (diff) | |
download | sonarqube-a53007e8246c8d44b0c9af4bd3757313c48dd230.tar.gz sonarqube-a53007e8246c8d44b0c9af4bd3757313c48dd230.zip |
SONAR-15966 Use Spring instead of Pico as dependency injection framework in the scanner-engine
Co-authored-by: Zipeng WU <zipeng.wu@sonarsource.com>
104 files changed, 1535 insertions, 659 deletions
diff --git a/build.gradle b/build.gradle index b34e90e9150..36d1474a37d 100644 --- a/build.gradle +++ b/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' diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/AbstractComputationSteps.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/AbstractComputationSteps.java index cb64a402b53..ad981b68bba 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/AbstractComputationSteps.java +++ b/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; } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/AuditPurgeTaskProcessor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/AuditPurgeTaskProcessor.java index 60102c1f78b..be26b4774f4 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/AuditPurgeTaskProcessor.java +++ b/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); } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/IssueSyncTaskProcessor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/IssueSyncTaskProcessor.java index dcfb9781714..29879730aa9 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/IssueSyncTaskProcessor.java +++ b/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); } diff --git a/server/sonar-ce-task/src/main/java/org/sonar/ce/task/container/TaskContainer.java b/server/sonar-ce-task/src/main/java/org/sonar/ce/task/container/TaskContainer.java index 7c3086ef4b4..2a3979f1c7f 100644 --- a/server/sonar-ce-task/src/main/java/org/sonar/ce/task/container/TaskContainer.java +++ b/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(); diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/engine/MigrationContainer.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/engine/MigrationContainer.java index f8bd5ac6084..c21a6cdf794 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/engine/MigrationContainer.java +++ b/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. diff --git a/sonar-core/build.gradle b/sonar-core/build.gradle index 3b658b278c9..3141d504391 100644 --- a/sonar-core/build.gradle +++ b/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') diff --git a/sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsInstaller.java b/sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsInstaller.java index f921ac2abc6..bae7811e160 100644 --- a/sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsInstaller.java +++ b/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; + } } } diff --git a/sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsLoader.java b/sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsLoader.java index 0109f30d357..3791f996640 100644 --- a/sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsLoader.java +++ b/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()); } diff --git a/sonar-core/src/main/java/org/sonar/core/metric/ScannerMetrics.java b/sonar-core/src/main/java/org/sonar/core/metric/ScannerMetrics.java index 4ca313de25c..4057b9ad1d5 100644 --- a/sonar-core/src/main/java/org/sonar/core/metric/ScannerMetrics.java +++ b/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()); } diff --git a/sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java b/sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java index 269ac851746..b8d7c56b310 100644 --- a/sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java +++ b/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) { diff --git a/sonar-core/src/main/java/org/sonar/core/platform/ComponentKeys.java b/sonar-core/src/main/java/org/sonar/core/platform/ComponentKeys.java index 7cb156b91bd..81a1b822b9d 100644 --- a/sonar-core/src/main/java/org/sonar/core/platform/ComponentKeys.java +++ b/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; } } diff --git a/sonar-core/src/main/java/org/sonar/core/platform/Container.java b/sonar-core/src/main/java/org/sonar/core/platform/Container.java new file mode 100644 index 00000000000..e7a9963623d --- /dev/null +++ b/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(); +} diff --git a/sonar-core/src/main/java/org/sonar/core/platform/ContainerPopulator.java b/sonar-core/src/main/java/org/sonar/core/platform/ContainerPopulator.java index c582cfead3f..f5a6fe46be5 100644 --- a/sonar-core/src/main/java/org/sonar/core/platform/ContainerPopulator.java +++ b/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); - } } diff --git a/sonar-core/src/main/java/org/sonar/core/platform/ExtensionContainer.java b/sonar-core/src/main/java/org/sonar/core/platform/ExtensionContainer.java new file mode 100644 index 00000000000..0bf945711c5 --- /dev/null +++ b/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(); +} diff --git a/sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java b/sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java index 9fea2f6f74b..93f12376c92 100644 --- a/sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java +++ b/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); } diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/DefaultTempFolder.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/DefaultTempFolder.java index dad6280f08e..15cba78e2e1 100644 --- a/sonar-plugin-api-impl/src/main/java/org/sonar/api/impl/utils/DefaultTempFolder.java +++ b/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(); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/resources/LanguagesTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/resources/LanguagesTest.java index 7df44279de2..5b8fb2a8f49 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/resources/LanguagesTest.java +++ b/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"); diff --git a/sonar-scanner-engine/build.gradle b/sonar-scanner-engine/build.gradle index 5afaba8d774..f3fa9ffdad9 100644 --- a/sonar-scanner-engine/build.gradle +++ b/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') diff --git a/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/Batch.java b/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/Batch.java index c1a672ce590..5d616b9e035 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/batch/bootstrapper/Batch.java +++ b/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); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ProjectInfo.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ProjectInfo.java index cf130f161f2..8c7a8309fa5 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ProjectInfo.java +++ b/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; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/AnalysisTempFolderProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/AnalysisTempFolderProvider.java index da406611440..753a6f3b711 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/AnalysisTempFolderProvider.java +++ b/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); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/AbstractExtensionDictionary.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/AbstractExtensionDictionary.java index 46b79847d06..6a8c5071466 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/AbstractExtensionDictionary.java +++ b/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); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ClassDerivedBeanDefinition.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ClassDerivedBeanDefinition.java new file mode 100644 index 00000000000..0743b81f1f6 --- /dev/null +++ b/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); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ExtensionInstaller.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ExtensionInstaller.java index ee037f90c46..a749bf13b84 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ExtensionInstaller.java +++ b/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 { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalConfiguration.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalConfiguration.java index f0fb379f5b6..19070c28360 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalConfiguration.java +++ b/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); } - } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalConfigurationProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalConfigurationProvider.java index cad8c08c367..af1323367ee 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalConfigurationProvider.java +++ b/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); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalServerSettingsProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalServerSettingsProvider.java index 9a373193f7f..8f8bca6dea6 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalServerSettingsProvider.java +++ b/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); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalTempFolderProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalTempFolderProvider.java index 0fdf444b7c9..4cc825c1930 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalTempFolderProvider.java +++ b/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; - } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/LazyBeanFactoryPostProcessor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/LazyBeanFactoryPostProcessor.java new file mode 100644 index 00000000000..61fcb419d60 --- /dev/null +++ b/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); + } + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginFiles.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginFiles.java index 371df48fab5..8e31b44d4ad 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginFiles.java +++ b/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); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionary.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionary.java index 171376a5fcb..9f94b6fe43b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionary.java +++ b/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; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PriorityBeanFactory.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PriorityBeanFactory.java new file mode 100644 index 00000000000..6d5a73b2369 --- /dev/null +++ b/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); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginRepository.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginRepository.java index c62fc09908a..fcf68cc3a04 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerPluginRepository.java +++ b/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; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java index db3abc561b1..678b26f17fd 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java +++ b/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); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringComponentContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringComponentContainer.java new file mode 100644 index 00000000000..0e1a3ad9d31 --- /dev/null +++ b/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 + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringGlobalContainer.java index 84e3f95b72c..fb0f25eaf76 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java +++ b/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); } - } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/StartableBeanPostProcessor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/StartableBeanPostProcessor.java new file mode 100644 index 00000000000..3bb4cb5570a --- /dev/null +++ b/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); + } + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationProvider.java index 12cb331a398..ebb55b9910c 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationProvider.java +++ b/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) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cpd/CpdExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/cpd/CpdExecutor.java index 017051f4118..41c6ec4102b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/cpd/CpdExecutor.java +++ b/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; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/IssueFilters.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/IssueFilters.java index ecaaa7d8f1b..1d850c39a4d 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/IssueFilters.java +++ b/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]); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisObserver.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisObserver.java index 3fe40990f84..77fac1555cc 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisObserver.java +++ b/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); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisObservers.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisObservers.java index 088c15e175b..9fe59b99499 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisObservers.java +++ b/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); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java index e9eaaf6c84b..1f002bf75bd 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/AnalysisResult.java +++ b/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); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/FakePluginInstaller.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/FakePluginInstaller.java index ea08a9ae8d5..5800b912a7b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/mediumtest/FakePluginInstaller.java +++ b/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<>(); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/qualitygate/QualityGateCheck.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/qualitygate/QualityGateCheck.java index a18b95b06d5..4ec321fd5e0 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/qualitygate/QualityGateCheck.java +++ b/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; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java index 2bf6e977297..e5abefb3a4f 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java +++ b/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; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java index 5c2bbb19e49..abf89bae8e5 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java +++ b/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()) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/MetricsRepositoryProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/MetricsRepositoryProvider.java index d5685073e5e..54ba26c6f4f 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/MetricsRepositoryProvider.java +++ b/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; } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfilesProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfilesProvider.java index 37bb0d1c04e..374d4ae0934 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/QualityProfilesProvider.java +++ b/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; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/DefaultLanguagesRepository.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/DefaultLanguagesRepository.java index 9a5f8fdffdf..acfd8a0a455 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/language/DefaultLanguagesRepository.java +++ b/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; /** diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/settings/DefaultGlobalSettingsLoader.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/settings/DefaultGlobalSettingsLoader.java index b0bc4886986..07f3a3c1aa2 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/settings/DefaultGlobalSettingsLoader.java +++ b/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); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesProvider.java index e6731d5df87..71ecf104b9b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/ActiveRulesProvider.java +++ b/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) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RulesProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RulesProvider.java index e2f82b3d165..9c05e4fece3 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/RulesProvider.java +++ b/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(); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputModuleHierarchyProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputModuleHierarchyProvider.java index 940e0ac9dd8..8915a7ab672 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputModuleHierarchyProvider.java +++ b/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, diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputProjectProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputProjectProvider.java index 8bcb781e23f..b5629ce69ef 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputProjectProvider.java +++ b/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; } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguagesProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguagesProvider.java new file mode 100644 index 00000000000..d1c3d972350 --- /dev/null +++ b/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])); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleConfiguration.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleConfiguration.java index 65b4a945f91..3abef362efb 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleConfiguration.java +++ b/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); } - } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleConfigurationProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleConfigurationProvider.java index 1728d29537b..5cb88b0e7b3 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleConfigurationProvider.java +++ b/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) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java index 69974fccd06..517e995af4f 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleIndexer.java +++ b/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; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableModuleSettings.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableModuleSettings.java index c4d50aa3959..a6cdc6b853f 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableModuleSettings.java +++ b/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<>(); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableProjectReactorProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableProjectReactorProvider.java index 242eec3bd58..7bdc9a2bd4d 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableProjectReactorProvider.java +++ b/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(); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableProjectSettings.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableProjectSettings.java index cccd0a1c1d6..a521aa96a45 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/MutableProjectSettings.java +++ b/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<>(); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectBuildersExecutor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectBuildersExecutor.java index b45e9f5cfa8..2d214650ce7 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectBuildersExecutor.java +++ b/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]); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectConfiguration.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectConfiguration.java index 390ee96e80f..80a1e1fad78 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectConfiguration.java +++ b/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); } - } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectConfigurationProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectConfigurationProvider.java index 8c79c3965e2..d20ff578439 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectConfigurationProvider.java +++ b/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; } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectLock.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectLock.java index 1e9776e92d0..8463396f4f8 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectLock.java +++ b/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 { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorValidator.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorValidator.java index f32a52cb7bf..6b4f05f9d25 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorValidator.java +++ b/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); } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectServerSettingsProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectServerSettingsProvider.java index cc587573010..55516177aa9 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectServerSettingsProvider.java +++ b/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); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringModuleScanContainer.java index c7c17c76799..79a09172a31 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java +++ b/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(); } - } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java index 954a80ae271..d1d605f42c8 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java +++ b/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(); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/WorkDirectoriesInitializer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/WorkDirectoriesInitializer.java index ae662ef8e5e..b118a870ff7 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/WorkDirectoriesInitializer.java +++ b/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()); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/BranchConfigurationProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/BranchConfigurationProvider.java index 41085f8db9a..87287fadd29 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/BranchConfigurationProvider.java +++ b/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; } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/ProjectBranchesProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/ProjectBranchesProvider.java index d0f8c5f0b35..9e3ad167f27 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/ProjectBranchesProvider.java +++ b/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; } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/ProjectPullRequestsProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/ProjectPullRequestsProvider.java index b1bc7c85f97..0b2ebde0fa5 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/branch/ProjectPullRequestsProvider.java +++ b/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; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultModuleFileSystem.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultModuleFileSystem.java index d949f49ad7e..65e321006a4 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultModuleFileSystem.java +++ b/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); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultProjectFileSystem.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultProjectFileSystem.java index 57946189e3f..1311ff59214 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/DefaultProjectFileSystem.java +++ b/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); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java index 96b0974c98e..7ea8799c855 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/filesystem/FileIndexer.java +++ b/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 { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFilesProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFilesProvider.java index 071864ac29b..1a7acc61189 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmChangedFilesProvider.java +++ b/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) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java index 05be6c2595a..25d91d49d31 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmConfiguration.java +++ b/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()) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorContext.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorContext.java index 4874b528357..a33a00961f4 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorContext.java +++ b/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; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorExtensionDictionary.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorExtensionDictionary.java index 34366b17d9e..d723bb2ebf3 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorExtensionDictionary.java +++ b/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; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorExtensionDictionary.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorExtensionDictionary.java index 2352db54cba..60b31745d19 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorExtensionDictionary.java +++ b/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; diff --git a/sonar-scanner-engine/src/main/resources/org/sonar/batch/bootstrapper/logback.xml b/sonar-scanner-engine/src/main/resources/org/sonar/batch/bootstrapper/logback.xml index 286c20903dc..b61685130a1 100644 --- a/sonar-scanner-engine/src/main/resources/org/sonar/batch/bootstrapper/logback.xml +++ b/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 --> diff --git a/sonar-scanner-engine/src/main/resources/org/sonar/batch/logback.xml b/sonar-scanner-engine/src/main/resources/org/sonar/batch/logback.xml index 6771813bfcd..4763605d094 100644 --- a/sonar-scanner-engine/src/main/resources/org/sonar/batch/logback.xml +++ b/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}"/> diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalContainerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalContainerTest.java deleted file mode 100644 index 0191ac400fe..00000000000 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/GlobalContainerTest.java +++ /dev/null @@ -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 { - - } - -} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/LazyBeanFactoryPostProcessorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/LazyBeanFactoryPostProcessorTest.java new file mode 100644 index 00000000000..04327d52720 --- /dev/null +++ b/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(); + } + +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ModuleSensorExtensionDictionaryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ModuleSensorExtensionDictionaryTest.java index 3c673ce2629..b2625033efc 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ModuleSensorExtensionDictionaryTest.java +++ b/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); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PriorityBeanFactoryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PriorityBeanFactoryTest.java new file mode 100644 index 00000000000..b20e87e9a26 --- /dev/null +++ b/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 { + + } + +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java index 3acd5700c73..4fe6fd6dad8 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ScannerWsClientProviderTest.java +++ b/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); - } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringComponentContainerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringComponentContainerTest.java new file mode 100644 index 00000000000..bbc00cf338a --- /dev/null +++ b/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); + } + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringGlobalContainerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringGlobalContainerTest.java new file mode 100644 index 00000000000..16a18dcfb12 --- /dev/null +++ b/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"); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/StartableBeanPostProcessorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/StartableBeanPostProcessorTest.java new file mode 100644 index 00000000000..ecdb6164cac --- /dev/null +++ b/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); + } + +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java index 75d9bb5388e..d560991ad50 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/ScannerMediumTester.java +++ b/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 { + + } + } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/NoLanguagesPluginsMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/NoLanguagesPluginsMediumTest.java index e19a3d67453..3f969ca4963 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/fs/NoLanguagesPluginsMediumTest.java +++ b/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 { diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/issues/IssuesMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/issues/IssuesMediumTest.java index dd1e4f496f2..1cef430e5b7 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/issues/IssuesMediumTest.java +++ b/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); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/log/ExceptionHandlingMediumTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/log/ExceptionHandlingMediumTest.java index 6124897f857..7ddbe5534e3 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/mediumtest/log/ExceptionHandlingMediumTest.java +++ b/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; diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java index bcef91c29ac..d2db79abfa7 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java +++ b/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(); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectScanContainerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/SpringProjectScanContainerTest.java index 36762ca8c90..1d8ba32c327 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectScanContainerTest.java +++ b/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(); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java index 3266125d64a..ec873cf72ae 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java @@ -62,18 +62,18 @@ public class WorkDirectoriesInitializerTest { when(root.getWorkDir()).thenReturn(rootWorkDir.toPath()); assertThat(rootWorkDir.list().length).isGreaterThan(1); - initializer = new WorkDirectoriesInitializer(hierarchy); + initializer = new WorkDirectoriesInitializer(); } @Test public void testNonExisting() { temp.delete(); - initializer.execute(); + initializer.execute(hierarchy); } @Test public void testClean() { - initializer.execute(); + initializer.execute(hierarchy); assertThat(rootWorkDir).exists(); assertThat(lock).exists(); @@ -89,7 +89,7 @@ public class WorkDirectoriesInitializerTest { moduleAWorkdir.mkdir(); new File(moduleAWorkdir, "fooA.txt").createNewFile(); - initializer.execute(); + initializer.execute(hierarchy); assertThat(rootWorkDir).exists(); assertThat(lock).exists(); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java index b036f742b03..9ce2b0e1bd8 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/BranchConfigurationProviderTest.java @@ -52,12 +52,6 @@ public class BranchConfigurationProviderTest { } @Test - public void should_cache_config() { - BranchConfiguration configuration = provider.provide(null, projectConfiguration, branches, pullRequests); - assertThat(provider.provide(null, projectConfiguration, branches, pullRequests)).isSameAs(configuration); - } - - @Test public void should_use_loader() { when(loader.load(eq(projectSettings), eq(branches), eq(pullRequests))).thenReturn(config); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesProviderTest.java index 3b19ae7cea1..e357a5ef36b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectBranchesProviderTest.java @@ -42,13 +42,6 @@ public class ProjectBranchesProviderTest { } @Test - public void should_cache_branches() { - when(scannerProperties.getProjectKey()).thenReturn("project"); - ProjectBranches branches = provider.provide(null, scannerProperties); - assertThat(provider.provide(null, scannerProperties)).isSameAs(branches); - } - - @Test public void should_use_loader() { when(scannerProperties.getProjectKey()).thenReturn("key"); when(mockLoader.load("key")).thenReturn(mockBranches); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectPullRequestsProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectPullRequestsProviderTest.java index 255bb37df41..5749445200b 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectPullRequestsProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/branch/ProjectPullRequestsProviderTest.java @@ -42,14 +42,6 @@ public class ProjectPullRequestsProviderTest { } @Test - public void cache_pull_requests() { - when(scannerProperties.getProjectKey()).thenReturn("project"); - ProjectPullRequests pullRequests = provider.provide(null, scannerProperties); - - assertThat(provider.provide(null, scannerProperties)).isSameAs(pullRequests); - } - - @Test public void should_use_loader() { when(scannerProperties.getProjectKey()).thenReturn("key"); when(mockLoader.load("key")).thenReturn(pullRequests); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java index cd8987c1ea3..d8c1576c289 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scm/ScmChangedFilesProviderTest.java @@ -134,11 +134,4 @@ public class ScmChangedFilesProviderTest { verify(scmProvider).branchChangedFiles("target", rootBaseDir); } - @Test - public void testCacheObject() { - provider.provide(scmConfiguration, branchConfiguration, project); - provider.provide(scmConfiguration, branchConfiguration, project); - verify(branchConfiguration).isPullRequest(); - } - } |