diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2022-02-01 15:16:25 -0600 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-02-22 20:02:46 +0000 |
commit | 60c1a4038e041a342dda9810e6fd761d66b01bdb (patch) | |
tree | 0e76b4252e4d7d257cf4ddcb6f081996bb1e03ab /sonar-scanner-engine | |
parent | 9694d4113bf401b84e86e0223dbea8f5339388d8 (diff) | |
download | sonarqube-60c1a4038e041a342dda9810e6fd761d66b01bdb.tar.gz sonarqube-60c1a4038e041a342dda9810e6fd761d66b01bdb.zip |
SONAR-15994 Migrate Sonarqube IOC framework from Pico to Spring
Diffstat (limited to 'sonar-scanner-engine')
27 files changed, 174 insertions, 1160 deletions
diff --git a/sonar-scanner-engine/build.gradle b/sonar-scanner-engine/build.gradle index f3fa9ffdad9..3aa87f8962b 100644 --- a/sonar-scanner-engine/build.gradle +++ b/sonar-scanner-engine/build.gradle @@ -29,7 +29,6 @@ dependencies { compile 'javax.annotation:javax.annotation-api' compile 'org.eclipse.jgit:org.eclipse.jgit' compile 'org.tmatesoft.svnkit:svnkit' - compile 'org.picocontainer:picocontainer' compile 'org.slf4j:jcl-over-slf4j' compile 'org.slf4j:jul-to-slf4j' compile 'org.slf4j:log4j-over-slf4j' @@ -60,7 +59,6 @@ dependencies { testCompile 'org.mockito:mockito-core' testCompile project(':plugins:sonar-xoo-plugin') testCompile project(':sonar-plugin-api').sourceSets.test.output - } license { 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 753a6f3b711..8bc4ec75ce5 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 @@ -30,7 +30,7 @@ import org.springframework.context.annotation.Bean; public class AnalysisTempFolderProvider { static final String TMP_NAME = ".sonartmp"; - @Bean("TempFolder") + @Bean("AnalysisTempFolder") public TempFolder provide(DefaultInputProject project) { Path workingDir = project.getWorkDir(); Path tempDir = workingDir.normalize().resolve(TMP_NAME); 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 deleted file mode 100644 index 0743b81f1f6..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ClassDerivedBeanDefinition.java +++ /dev/null @@ -1,62 +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 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/GlobalTempFolderProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalTempFolderProvider.java index 4cc825c1930..7eb63a5b9a0 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 @@ -19,32 +19,30 @@ */ package org.sonar.scanner.bootstrap; -import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.concurrent.TimeUnit; import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; -import org.sonar.api.Startable; import org.sonar.api.impl.utils.DefaultTempFolder; import org.sonar.api.utils.System2; import org.sonar.api.utils.TempFolder; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; +import static org.sonar.core.util.FileUtils.deleteQuietly; import org.springframework.context.annotation.Bean; -import static org.sonar.core.util.FileUtils.deleteQuietly; +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.concurrent.TimeUnit; -public class GlobalTempFolderProvider implements Startable { +public class GlobalTempFolderProvider { private static final Logger LOG = Loggers.get(GlobalTempFolderProvider.class); private static final long CLEAN_MAX_AGE = TimeUnit.DAYS.toMillis(21); static final String TMP_NAME_PREFIX = ".sonartmp_"; private System2 system; - private DefaultTempFolder tempFolder; public GlobalTempFolderProvider() { this(new System2()); @@ -54,26 +52,24 @@ public class GlobalTempFolderProvider implements Startable { this.system = system; } - @Bean("TempFolder") + @Bean("GlobalTempFolder") public TempFolder provide(ScannerProperties scannerProps) { - if (tempFolder == null) { - String workingPathName = StringUtils.defaultIfBlank(scannerProps.property(CoreProperties.GLOBAL_WORKING_DIRECTORY), CoreProperties.GLOBAL_WORKING_DIRECTORY_DEFAULT_VALUE); - Path workingPath = Paths.get(workingPathName); + String workingPathName = StringUtils.defaultIfBlank(scannerProps.property(CoreProperties.GLOBAL_WORKING_DIRECTORY), CoreProperties.GLOBAL_WORKING_DIRECTORY_DEFAULT_VALUE); + Path workingPath = Paths.get(workingPathName); - if (!workingPath.isAbsolute()) { - Path home = findSonarHome(scannerProps); - workingPath = home.resolve(workingPath).normalize(); - } - try { - cleanTempFolders(workingPath); - } catch (IOException e) { - LOG.error(String.format("failed to clean global working directory: %s", workingPath), e); - } - Path tempDir = createTempFolder(workingPath); - tempFolder = new DefaultTempFolder(tempDir.toFile(), true); + if (!workingPath.isAbsolute()) { + Path home = findSonarHome(scannerProps); + workingPath = home.resolve(workingPath).normalize(); } - return tempFolder; + try { + cleanTempFolders(workingPath); + } catch (IOException e) { + LOG.error(String.format("failed to clean global working directory: %s", workingPath), e); + } + Path tempDir = createTempFolder(workingPath); + return new DefaultTempFolder(tempDir.toFile(), true); + } private static Path createTempFolder(Path workingPath) { @@ -148,15 +144,4 @@ public class GlobalTempFolderProvider implements Startable { } } - @Override - public void start() { - // nothing to do - } - - @Override - public void stop() { - if (tempFolder != null) { - tempFolder.stop(); - } - } } 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 deleted file mode 100644 index 61fcb419d60..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/LazyBeanFactoryPostProcessor.java +++ /dev/null @@ -1,35 +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 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/PriorityBeanFactory.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PriorityBeanFactory.java deleted file mode 100644 index 6d5a73b2369..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PriorityBeanFactory.java +++ /dev/null @@ -1,123 +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 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/SpringComponentContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringComponentContainer.java deleted file mode 100644 index 17325193d5b..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringComponentContainer.java +++ /dev/null @@ -1,227 +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.Iterables; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; -import javax.annotation.CheckForNull; -import org.jetbrains.annotations.Nullable; -import org.sonar.api.config.PropertyDefinitions; -import org.sonar.api.utils.System2; -import org.sonar.core.platform.ComponentKeys; -import org.sonar.core.platform.Container; -import org.sonar.core.platform.ExtensionContainer; -import org.sonar.core.platform.PluginInfo; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; - -import static java.util.Collections.emptyList; -import static java.util.Optional.ofNullable; - -public class SpringComponentContainer implements ExtensionContainer { - protected final AnnotationConfigApplicationContext context; - @Nullable - protected final SpringComponentContainer parent; - - private final PropertyDefinitions propertyDefinitions; - private final ComponentKeys componentKeys = new ComponentKeys(); - - protected SpringComponentContainer() { - this(null, new PropertyDefinitions(System2.INSTANCE), emptyList()); - } - - protected SpringComponentContainer(List<?> externalExtensions) { - this(null, new PropertyDefinitions(System2.INSTANCE), externalExtensions); - } - - protected SpringComponentContainer(SpringComponentContainer parent) { - this(parent, parent.propertyDefinitions, emptyList()); - } - - private SpringComponentContainer(@Nullable SpringComponentContainer parent, PropertyDefinitions propertyDefinitions, List<?> externalExtensions) { - this.parent = parent; - this.propertyDefinitions = propertyDefinitions; - this.context = new AnnotationConfigApplicationContext(new PriorityBeanFactory()); - if (parent != null) { - context.setParent(parent.context); - } - add(this); - add(new StartableBeanPostProcessor()); - add(externalExtensions); - add(propertyDefinitions); - } - - /** - * Beans need to have a unique name, otherwise they'll override each other. - * The strategy is: - * - For classes, use the classloader + fully qualified class name as the name of the bean - * - For instances, use the Classloader + FQCN + toString() - * - If the object is a collection, iterate through the elements and apply the same strategy for each of them - */ - @Override - public Container add(Object... objects) { - for (Object o : objects) { - if (o instanceof Class) { - Class<?> clazz = (Class<?>) o; - context.registerBean(componentKeys.ofClass(clazz), clazz); - } else if (o instanceof Iterable) { - add(Iterables.toArray((Iterable<?>) o, Object.class)); - } else { - registerInstance(o); - } - } - return this; - } - - private <T> void registerInstance(T instance) { - Supplier<T> supplier = () -> instance; - Class<T> clazz = (Class<T>) instance.getClass(); - context.registerBean(componentKeys.ofInstance(instance), clazz, supplier); - declareExtension("", instance); - } - - /** - * Extensions are usually added by plugins and we assume they don't support any injection-related annotations. - * Spring contexts supporting annotations will fail if multiple constructors are present without any annotations indicating which one to use for injection. - * For that reason, we need to create the beans ourselves, using ClassDerivedBeanDefinition, which will declare that all constructors can be used for injection. - */ - private Container addExtension(Object o) { - if (o instanceof Class) { - Class<?> clazz = (Class<?>) o; - ClassDerivedBeanDefinition bd = new ClassDerivedBeanDefinition(clazz); - context.registerBeanDefinition(componentKeys.ofClass(clazz), bd); - } else if (o instanceof Iterable) { - ((Iterable<?>) o).forEach(this::addExtension); - } else { - ClassDerivedBeanDefinition bd = new ClassDerivedBeanDefinition(o.getClass()); - bd.setInstanceSupplier(() -> o); - context.registerBeanDefinition(componentKeys.ofInstance(o), bd); - } - return this; - } - - @Override - public Container addSingletons(Iterable<?> components) { - return add(components); - } - - @Override - public <T> T getComponentByType(Class<T> type) { - try { - return context.getBean(type); - } catch (Exception t) { - throw new IllegalStateException("Unable to load component " + type, t); - } - } - - @Override - public <T> List<T> getComponentsByType(Class<T> type) { - try { - return new ArrayList<>(context.getBeansOfType(type).values()); - } catch (Exception t) { - throw new IllegalStateException("Unable to load components " + type, t); - } - } - - public void execute() { - RuntimeException r = null; - try { - startComponents(); - } catch (RuntimeException e) { - r = e; - } finally { - try { - stopComponents(); - } catch (RuntimeException e) { - if (r == null) { - r = e; - } - } - } - if (r != null) { - throw r; - } - } - - public SpringComponentContainer startComponents() { - doBeforeStart(); - context.refresh(); - doAfterStart(); - return this; - } - - public SpringComponentContainer stopComponents() { - if (context.isActive()) { - context.close(); - } - return this; - } - - public SpringComponentContainer createChild() { - return new SpringComponentContainer(this); - } - - @Override - @CheckForNull - public SpringComponentContainer getParent() { - return parent; - } - - @Override - public SpringComponentContainer addExtension(@Nullable PluginInfo pluginInfo, Object extension) { - addExtension(extension); - declareExtension(pluginInfo, extension); - return this; - } - - @Override - public SpringComponentContainer addExtension(@Nullable String defaultCategory, Object extension) { - addExtension(extension); - declareExtension(defaultCategory, extension); - return this; - } - - @Override - public SpringComponentContainer declareExtension(@Nullable PluginInfo pluginInfo, Object extension) { - declareExtension(pluginInfo != null ? pluginInfo.getName() : "", extension); - return this; - } - - @Override - public SpringComponentContainer declareExtension(@Nullable String defaultCategory, Object extension) { - this.propertyDefinitions.addComponent(extension, ofNullable(defaultCategory).orElse("")); - return this; - } - - /** - * This method aims to be overridden - */ - protected void doBeforeStart() { - // nothing - } - - /** - * This method aims to be overridden - */ - protected void doAfterStart() { - // nothing - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringGlobalContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringGlobalContainer.java index fb0f25eaf76..4e85fc6c1cc 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringGlobalContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/SpringGlobalContainer.java @@ -43,6 +43,7 @@ import org.sonar.core.platform.PluginClassLoader; import org.sonar.core.platform.PluginClassloaderFactory; import org.sonar.core.platform.PluginInfo; import org.sonar.core.platform.PluginRepository; +import org.sonar.core.platform.SpringComponentContainer; import org.sonar.core.util.DefaultHttpDownloader; import org.sonar.core.util.UuidFactoryImpl; import org.sonar.scanner.extension.ScannerCoreExtensionsInstaller; 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 deleted file mode 100644 index 3bb4cb5570a..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/StartableBeanPostProcessor.java +++ /dev/null @@ -1,60 +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 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/scan/InputProjectProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/InputProjectProvider.java index b5629ce69ef..ac65a92484e 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 @@ -32,7 +32,7 @@ public class InputProjectProvider { @Bean("DefaultInputProject") public DefaultInputProject provide(ProjectBuildersExecutor projectBuildersExecutor, ProjectReactorValidator validator, - ProjectReactor projectReactor, ScannerComponentIdGenerator scannerComponentIdGenerator) { + ProjectReactor projectReactor, ScannerComponentIdGenerator scannerComponentIdGenerator, WorkDirectoriesInitializer workDirectoriesInit) { // 1 Apply project builders projectBuildersExecutor.execute(projectReactor); @@ -41,6 +41,7 @@ public class InputProjectProvider { // 3 Create project DefaultInputProject project = new DefaultInputProject(projectReactor.getRoot(), scannerComponentIdGenerator.getAsInt()); + workDirectoriesInit.execute(project); LOG.info("Project key: {}", project.key()); LOG.info("Base dir: {}", project.getBaseDir().toAbsolutePath().toString()); 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 deleted file mode 100644 index d1c3d972350..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/LanguagesProvider.java +++ /dev/null @@ -1,36 +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.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/SpringModuleScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringModuleScanContainer.java index 79a09172a31..4707354a706 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringModuleScanContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringModuleScanContainer.java @@ -23,7 +23,7 @@ import javax.annotation.Priority; import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.scan.filesystem.FileExclusions; import org.sonar.scanner.bootstrap.ExtensionInstaller; -import org.sonar.scanner.bootstrap.SpringComponentContainer; +import org.sonar.core.platform.SpringComponentContainer; import org.sonar.scanner.scan.filesystem.DefaultModuleFileSystem; import org.sonar.scanner.scan.filesystem.ModuleInputComponentStore; import org.sonar.scanner.sensor.ModuleSensorContext; diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java index 8320fa8a3fc..888f5661e8c 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/SpringProjectScanContainer.java @@ -33,6 +33,7 @@ import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.core.config.ScannerProperties; import org.sonar.core.extension.CoreExtensionsInstaller; +import org.sonar.core.language.LanguagesProvider; import org.sonar.core.metric.ScannerMetrics; import org.sonar.scanner.DefaultFileLinesContextFactory; import org.sonar.scanner.ProjectInfo; @@ -41,7 +42,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.core.platform.SpringComponentContainer; import org.sonar.scanner.ci.CiConfigurationProvider; import org.sonar.scanner.ci.vendors.AppVeyor; import org.sonar.scanner.ci.vendors.AwsCodeBuild; 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 b118a870ff7..11552502e00 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 @@ -24,26 +24,42 @@ import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Iterator; -import org.sonar.core.util.FileUtils; +import org.sonar.api.batch.fs.internal.AbstractProjectOrModule; import org.sonar.api.batch.fs.internal.DefaultInputModule; +import org.sonar.api.batch.fs.internal.DefaultInputProject; +import org.sonar.core.util.FileUtils; import org.sonar.scanner.fs.InputModuleHierarchy; /** - * Clean and create working directories of each module. + * Clean and create working directories of each module, except the root. * Be careful that sub module work dir might be nested in parent working directory. */ public class WorkDirectoriesInitializer { public void execute(InputModuleHierarchy moduleHierarchy) { - cleanAllWorkingDirs(moduleHierarchy, moduleHierarchy.root()); - mkdirsAllWorkingDirs(moduleHierarchy, moduleHierarchy.root()); + // dont apply to root. Root is done by InputProjectProvider + for (DefaultInputModule sub : moduleHierarchy.children(moduleHierarchy.root())) { + cleanAllWorkingDirs(moduleHierarchy, sub); + } + for (DefaultInputModule sub : moduleHierarchy.children(moduleHierarchy.root())) { + mkdirsAllWorkingDirs(moduleHierarchy, sub); + } + } + + public void execute(DefaultInputProject project) { + cleanWorkingDir(project); + mkdirWorkingDir(project); } private static void cleanAllWorkingDirs(InputModuleHierarchy moduleHierarchy, DefaultInputModule module) { for (DefaultInputModule sub : moduleHierarchy.children(module)) { cleanAllWorkingDirs(moduleHierarchy, sub); } - if (Files.exists(module.getWorkDir())) { - deleteAllRecursivelyExceptLockFile(module.getWorkDir()); + cleanWorkingDir(module); + } + + private static void cleanWorkingDir(AbstractProjectOrModule projectOrModule) { + if (Files.exists(projectOrModule.getWorkDir())) { + deleteAllRecursivelyExceptLockFile(projectOrModule.getWorkDir()); } } @@ -51,10 +67,14 @@ public class WorkDirectoriesInitializer { for (DefaultInputModule sub : moduleHierarchy.children(module)) { mkdirsAllWorkingDirs(moduleHierarchy, sub); } + mkdirWorkingDir(module); + } + + private static void mkdirWorkingDir(AbstractProjectOrModule projectOrModule) { try { - Files.createDirectories(module.getWorkDir()); + Files.createDirectories(projectOrModule.getWorkDir()); } catch (Exception e) { - throw new IllegalStateException("Fail to create working dir: " + module.getWorkDir(), e); + throw new IllegalStateException("Fail to create working dir: " + projectOrModule.getWorkDir(), e); } } 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 d723bb2ebf3..5764ba0c854 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 @@ -22,9 +22,8 @@ package org.sonar.scanner.sensor; import java.util.Collection; import java.util.stream.Collectors; import org.sonar.api.batch.sensor.Sensor; -import org.sonar.core.platform.ComponentContainer; +import org.sonar.core.platform.ExtensionContainer; import org.sonar.scanner.bootstrap.AbstractExtensionDictionary; -import org.sonar.scanner.bootstrap.SpringComponentContainer; import org.sonar.scanner.scan.branch.BranchConfiguration; import org.sonar.scanner.scan.filesystem.MutableFileSystem; @@ -35,7 +34,7 @@ public class ModuleSensorExtensionDictionary extends AbstractExtensionDictionary private final MutableFileSystem fileSystem; private final BranchConfiguration branchConfiguration; - public ModuleSensorExtensionDictionary(SpringComponentContainer componentContainer, ModuleSensorContext sensorContext, ModuleSensorOptimizer sensorOptimizer, + public ModuleSensorExtensionDictionary(ExtensionContainer componentContainer, ModuleSensorContext sensorContext, ModuleSensorOptimizer sensorOptimizer, MutableFileSystem fileSystem, BranchConfiguration branchConfiguration) { super(componentContainer); this.sensorContext = sensorContext; 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 60b31745d19..b33c96fa848 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 @@ -24,7 +24,7 @@ import java.util.List; import java.util.stream.Collectors; import org.sonar.api.scanner.sensor.ProjectSensor; import org.sonar.scanner.bootstrap.AbstractExtensionDictionary; -import org.sonar.scanner.bootstrap.SpringComponentContainer; +import org.sonar.core.platform.SpringComponentContainer; import org.sonar.scanner.scan.branch.BranchConfiguration; import org.sonar.scanner.scan.filesystem.MutableFileSystem; 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 b61685130a1..41ec1d712e5 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 @@ -33,7 +33,7 @@ <level value="INFO"/> </logger> - <logger name="org.sonar.scanner.bootstrap.PriorityBeanFactory"> + <logger name="org.sonar.core.platform.PriorityBeanFactory"> <level value="INFO"/> </logger> diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java index d4c61ca7d9d..9fcebc1958c 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/ExtensionInstallerTest.java @@ -20,13 +20,14 @@ package org.sonar.scanner.bootstrap; import java.util.Arrays; + import org.apache.commons.lang.ClassUtils; import org.junit.Test; import org.sonar.api.Plugin; import org.sonar.api.SonarRuntime; import org.sonar.api.batch.ScannerSide; import org.sonar.api.config.internal.MapSettings; -import org.sonar.core.platform.ComponentContainer; +import org.sonar.core.platform.ListContainer; import org.sonar.core.platform.PluginInfo; import static org.assertj.core.api.Assertions.assertThat; @@ -35,8 +36,8 @@ import static org.mockito.Mockito.when; public class ExtensionInstallerTest { - private MapSettings settings = new MapSettings(); - private ScannerPluginRepository pluginRepository = mock(ScannerPluginRepository.class); + private final MapSettings settings = new MapSettings(); + private final ScannerPluginRepository pluginRepository = mock(ScannerPluginRepository.class); private static Plugin newPluginInstance(final Object... extensions) { return desc -> desc.addExtensions(Arrays.asList(extensions)); @@ -47,12 +48,13 @@ public class ExtensionInstallerTest { when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo"))); when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(Foo.class, Bar.class)); - ComponentContainer container = new ComponentContainer(); + ListContainer container = new ListContainer(); ExtensionInstaller installer = new ExtensionInstaller(mock(SonarRuntime.class), pluginRepository, settings.asConfig()); installer.install(container, new FooMatcher()); - assertThat(container.getComponentByType(Foo.class)).isNotNull(); - assertThat(container.getComponentByType(Bar.class)).isNull(); + assertThat(container.getAddedObjects()) + .contains(Foo.class) + .doesNotContain(Bar.class); } private static class FooMatcher implements ExtensionMatcher { 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 deleted file mode 100644 index 04327d52720..00000000000 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/LazyBeanFactoryPostProcessorTest.java +++ /dev/null @@ -1,41 +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 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 b2625033efc..2246bd1914d 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 @@ -19,21 +19,21 @@ */ package org.sonar.scanner.bootstrap; -import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; import org.junit.Before; import org.junit.Test; -import org.picocontainer.behaviors.FieldDecorated; import org.sonar.api.batch.DependedUpon; import org.sonar.api.batch.DependsUpon; import org.sonar.api.batch.Phase; import org.sonar.api.batch.ScannerSide; -import org.sonar.api.batch.bootstrap.ProjectDefinition; -import org.sonar.api.batch.fs.internal.DefaultInputModule; import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.SensorDescriptor; import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor; -import org.sonar.scanner.scan.SpringModuleScanContainer; +import org.sonar.core.platform.ExtensionContainer; import org.sonar.scanner.scan.branch.BranchConfiguration; import org.sonar.scanner.scan.filesystem.MutableFileSystem; import org.sonar.scanner.sensor.ModuleSensorContext; @@ -41,10 +41,6 @@ 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; @@ -61,17 +57,9 @@ public class ModuleSensorExtensionDictionaryTest { when(sensorOptimizer.shouldExecute(any(DefaultSensorDescriptor.class))).thenReturn(true); } - private ModuleSensorExtensionDictionary newSelector(Object... extensions) { - DefaultInputModule inputModule = mock(DefaultInputModule.class); - when(inputModule.definition()).thenReturn(mock(ProjectDefinition.class)); - - SpringComponentContainer parent = new SpringComponentContainer(); - parent.context.refresh(); - - SpringComponentContainer iocContainer = new SpringModuleScanContainer(parent, inputModule); - iocContainer.add(Arrays.asList(extensions)); - iocContainer.context.refresh(); - + private ModuleSensorExtensionDictionary newSelector(Class type, Object... instances) { + ExtensionContainer iocContainer = mock(ExtensionContainer.class); + when(iocContainer.getComponentsByType(type)).thenReturn(Arrays.asList(instances)); return new ModuleSensorExtensionDictionary(iocContainer, mock(ModuleSensorContext.class), sensorOptimizer, fileSystem, branchConfiguration); } @@ -80,7 +68,7 @@ public class ModuleSensorExtensionDictionaryTest { final Sensor sensor1 = new FakeSensor(); final Sensor sensor2 = new FakeSensor(); - ModuleSensorExtensionDictionary selector = newSelector(sensor1, sensor2); + ModuleSensorExtensionDictionary selector = newSelector(Sensor.class, sensor1, sensor2); Collection<Sensor> sensors = selector.select(Sensor.class, true, extension -> extension.equals(sensor1)); assertThat(sensors).contains(sensor1); assertEquals(1, sensors.size()); @@ -90,9 +78,8 @@ public class ModuleSensorExtensionDictionaryTest { public void testGetFilteredExtensions() { Sensor sensor1 = new FakeSensor(); Sensor sensor2 = new FakeSensor(); - FieldDecorated.Decorator decorator = mock(FieldDecorated.Decorator.class); - ModuleSensorExtensionDictionary selector = newSelector(sensor1, sensor2, decorator); + ModuleSensorExtensionDictionary selector = newSelector(Sensor.class, sensor1, sensor2); Collection<Sensor> sensors = selector.select(Sensor.class, false, null); assertThat(sensors).containsOnly(sensor1, sensor2); @@ -104,17 +91,16 @@ public class ModuleSensorExtensionDictionaryTest { Sensor b = new FakeSensor(); Sensor c = new FakeSensor(); - SpringComponentContainer grandParent = new SpringComponentContainer(); - grandParent.add(a); - grandParent.context.refresh(); + ExtensionContainer grandParent = mock(ExtensionContainer.class); + when(grandParent.getComponentsByType(Sensor.class)).thenReturn(List.of(a)); - SpringComponentContainer parent = grandParent.createChild(); - parent.add(b); - parent.context.refresh(); + ExtensionContainer parent = mock(ExtensionContainer.class); + when(parent.getComponentsByType(Sensor.class)).thenReturn(List.of(b)); + when(parent.getParent()).thenReturn(grandParent); - SpringComponentContainer child = parent.createChild(); - child.add(c); - child.context.refresh(); + ExtensionContainer child = mock(ExtensionContainer.class); + when(child.getComponentsByType(Sensor.class)).thenReturn(List.of(c)); + when(child.getParent()).thenReturn(parent); ModuleSensorExtensionDictionary dictionnary = new ModuleSensorExtensionDictionary(child, mock(ModuleSensorContext.class), mock(ModuleSensorOptimizer.class), fileSystem, branchConfiguration); @@ -127,8 +113,8 @@ public class ModuleSensorExtensionDictionaryTest { Object b = new MethodDependentOf(a); Object c = new MethodDependentOf(b); - ModuleSensorExtensionDictionary selector = newSelector(b, c, a); - List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + ModuleSensorExtensionDictionary selector = newSelector(Marker.class, b, c, a); + List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(3); assertThat(extensions.get(0)).isEqualTo(a); @@ -141,16 +127,16 @@ public class ModuleSensorExtensionDictionaryTest { Object a = new GeneratesSomething("foo"); Object b = new MethodDependentOf("foo"); - ModuleSensorExtensionDictionary selector = newSelector(a, b); - List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + ModuleSensorExtensionDictionary selector = newSelector(Marker.class, a, b); + List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions.size()).isEqualTo(2); assertThat(extensions.get(0)).isEqualTo(a); assertThat(extensions.get(1)).isEqualTo(b); // different initial order - selector = newSelector(b, a); - extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + selector = newSelector(Marker.class, b, a); + extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); assertThat(extensions.get(0)).isEqualTo(a); @@ -162,16 +148,16 @@ public class ModuleSensorExtensionDictionaryTest { Object a = new GeneratesSomething("foo"); Object b = new MethodDependentOf(Arrays.asList("foo")); - ModuleSensorExtensionDictionary selector = newSelector(a, b); - List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + ModuleSensorExtensionDictionary selector = newSelector(Marker.class, a, b); + List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); assertThat(extensions.get(0)).isEqualTo(a); assertThat(extensions.get(1)).isEqualTo(b); // different initial order - selector = newSelector(b, a); - extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + selector = newSelector(Marker.class, b, a); + extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); assertThat(extensions.get(0)).isEqualTo(a); @@ -183,16 +169,16 @@ public class ModuleSensorExtensionDictionaryTest { Object a = new GeneratesSomething("foo"); Object b = new MethodDependentOf(new String[] {"foo"}); - ModuleSensorExtensionDictionary selector = newSelector(a, b); - List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + ModuleSensorExtensionDictionary selector = newSelector(Marker.class, a, b); + List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); assertThat(extensions.get(0)).isEqualTo(a); assertThat(extensions.get(1)).isEqualTo(b); // different initial order - selector = newSelector(b, a); - extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + selector = newSelector(Marker.class, b, a); + extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); assertThat(extensions.get(0)).isEqualTo(a); @@ -204,16 +190,16 @@ public class ModuleSensorExtensionDictionaryTest { Object a = new ClassDependedUpon(); Object b = new ClassDependsUpon(); - ModuleSensorExtensionDictionary selector = newSelector(a, b); - List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + ModuleSensorExtensionDictionary selector = newSelector(Marker.class, a, b); + List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); assertThat(extensions.get(0)).isEqualTo(a); assertThat(extensions.get(1)).isEqualTo(b); // different initial order - selector = newSelector(b, a); - extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + selector = newSelector(Marker.class, b, a); + extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); assertThat(extensions.get(0)).isEqualTo(a); @@ -227,16 +213,16 @@ public class ModuleSensorExtensionDictionaryTest { Object b = new InterfaceDependsUpon() { }; - ModuleSensorExtensionDictionary selector = newSelector(a, b); - List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + ModuleSensorExtensionDictionary selector = newSelector(Marker.class, a, b); + List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); assertThat(extensions.get(0)).isEqualTo(a); assertThat(extensions.get(1)).isEqualTo(b); // different initial order - selector = newSelector(b, a); - extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + selector = newSelector(Marker.class, b, a); + extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); assertThat(extensions.get(0)).isEqualTo(a); @@ -248,16 +234,16 @@ public class ModuleSensorExtensionDictionaryTest { Object a = new SubClass("foo"); Object b = new MethodDependentOf("foo"); - ModuleSensorExtensionDictionary selector = newSelector(b, a); - List<Object> extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + ModuleSensorExtensionDictionary selector = newSelector(Marker.class, b, a); + List<Object> extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); assertThat(extensions.get(0)).isEqualTo(a); assertThat(extensions.get(1)).isEqualTo(b); // change initial order - selector = newSelector(a, b); - extensions = Lists.newArrayList(selector.select(Marker.class, true, null)); + selector = newSelector(Marker.class, a, b); + extensions = new ArrayList<>(selector.select(Marker.class, true, null)); assertThat(extensions).hasSize(2); assertThat(extensions.get(0)).isEqualTo(a); @@ -266,7 +252,8 @@ public class ModuleSensorExtensionDictionaryTest { @Test(expected = IllegalStateException.class) public void annotatedMethodsCanNotBePrivate() { - ModuleSensorExtensionDictionary selector = newSelector(); + ModuleSensorExtensionDictionary selector = new ModuleSensorExtensionDictionary(mock(ExtensionContainer.class), mock(ModuleSensorContext.class), + sensorOptimizer, fileSystem, branchConfiguration); Object wrong = new Object() { @DependsUpon private Object foo() { @@ -282,7 +269,7 @@ public class ModuleSensorExtensionDictionaryTest { NormalSensor normal = new NormalSensor(); PostSensor post = new PostSensor(); - ModuleSensorExtensionDictionary selector = newSelector(normal, post, pre); + ModuleSensorExtensionDictionary selector = newSelector(Sensor.class, normal, post, pre); assertThat(selector.selectSensors(false)).extracting("wrappedSensor").containsExactly(pre, normal, post); } @@ -292,8 +279,8 @@ public class ModuleSensorExtensionDictionaryTest { NormalSensor normal = new NormalSensor(); PostSensorSubclass post = new PostSensorSubclass(); - ModuleSensorExtensionDictionary selector = newSelector(normal, post, pre); - List extensions = Lists.newArrayList(selector.select(Sensor.class, true, null)); + ModuleSensorExtensionDictionary selector = newSelector(Sensor.class, normal, post, pre); + List extensions = new ArrayList<>(selector.select(Sensor.class, true, null)); assertThat(extensions).containsExactly(pre, normal, post); } @@ -302,7 +289,7 @@ public class ModuleSensorExtensionDictionaryTest { public void selectSensors() { FakeSensor nonGlobalSensor = new FakeSensor(); FakeGlobalSensor globalSensor = new FakeGlobalSensor(); - ModuleSensorExtensionDictionary selector = newSelector(nonGlobalSensor, globalSensor); + ModuleSensorExtensionDictionary selector = newSelector(Sensor.class, nonGlobalSensor, globalSensor); // verify non-global sensor Collection<ModuleSensorWrapper> extensions = selector.selectSensors(false); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionaryTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionaryTest.java index e359a0f1be6..dbfd4bd9f5c 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionaryTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PostJobExtensionDictionaryTest.java @@ -19,6 +19,7 @@ */ package org.sonar.scanner.bootstrap; +import java.util.List; import org.junit.Before; import org.junit.Test; import org.sonar.api.batch.Phase; @@ -26,10 +27,7 @@ import org.sonar.api.batch.postjob.PostJob; import org.sonar.api.batch.postjob.PostJobContext; import org.sonar.api.batch.postjob.PostJobDescriptor; import org.sonar.api.batch.postjob.internal.DefaultPostJobDescriptor; -import org.sonar.api.batch.sensor.Sensor; -import org.sonar.api.batch.sensor.SensorContext; -import org.sonar.api.batch.sensor.SensorDescriptor; -import org.sonar.core.platform.ComponentContainer; +import org.sonar.core.platform.ExtensionContainer; import org.sonar.scanner.postjob.PostJobOptimizer; import static org.assertj.core.api.Assertions.assertThat; @@ -38,49 +36,23 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class PostJobExtensionDictionaryTest { - private PostJobOptimizer postJobOptimizer = mock(PostJobOptimizer.class); + private final PostJobOptimizer postJobOptimizer = mock(PostJobOptimizer.class); @Before public void setUp() { when(postJobOptimizer.shouldExecute(any(DefaultPostJobDescriptor.class))).thenReturn(true); } - private PostJobExtensionDictionary newSelector(Object... extensions) { - ComponentContainer iocContainer = new ComponentContainer(); - for (Object extension : extensions) { - iocContainer.addSingleton(extension); - } - return new PostJobExtensionDictionary(iocContainer, postJobOptimizer, mock(PostJobContext.class)); - } - @Test public void dependsUponPhaseForPostJob() { PrePostJob pre = new PrePostJob(); NormalPostJob normal = new NormalPostJob(); - PostJobExtensionDictionary selector = newSelector(normal, pre); - assertThat(selector.selectPostJobs()).extracting("wrappedPostJob").containsExactly(pre, normal); - } - - interface Marker { - - } - - @Phase(name = Phase.Name.POST) static - class PostSensor implements Sensor { - - @Override - public void describe(SensorDescriptor descriptor) { - } - - @Override - public void execute(SensorContext context) { - } - - } - - class PostSensorSubclass extends PostSensor { + ExtensionContainer iocContainer = mock(ExtensionContainer.class); + when(iocContainer.getComponentsByType(PostJob.class)).thenReturn(List.of(pre, normal)); + PostJobExtensionDictionary selector = new PostJobExtensionDictionary(iocContainer, postJobOptimizer, mock(PostJobContext.class)); + assertThat(selector.selectPostJobs()).extracting("wrappedPostJob").containsExactly(pre, normal); } static class NormalPostJob implements PostJob { 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 deleted file mode 100644 index b20e87e9a26..00000000000 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PriorityBeanFactoryTest.java +++ /dev/null @@ -1,103 +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 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/SpringComponentContainerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringComponentContainerTest.java deleted file mode 100644 index 7c1008b4938..00000000000 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/SpringComponentContainerTest.java +++ /dev/null @@ -1,217 +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 javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; -import org.junit.Test; -import org.sonar.api.Startable; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertThrows; - -public class SpringComponentContainerTest { - - @Test - public void should_stop_after_failing() { - ApiStartable startStop = new ApiStartable(); - SpringComponentContainer container = new SpringComponentContainer() { - @Override - public void doBeforeStart() { - add(startStop); - } - - @Override - public void doAfterStart() { - getComponentByType(ApiStartable.class); - throw new IllegalStateException("doBeforeStart"); - } - }; - - assertThrows("doBeforeStart", IllegalStateException.class, container::execute); - assertThat(startStop.start).isTrue(); - assertThat(startStop.stop).isTrue(); - } - - @Test - public void register_instance_with_toString() { - SpringComponentContainer container = new SimpleContainer(new ToString("a"), new ToString("b")); - container.startComponents(); - assertThat(container.context.getBeanDefinitionNames()) - .contains( - this.getClass().getClassLoader() + "-org.sonar.scanner.bootstrap.SpringComponentContainerTest.ToString-a", - this.getClass().getClassLoader() + "-org.sonar.scanner.bootstrap.SpringComponentContainerTest.ToString-b"); - assertThat(container.getComponentsByType(ToString.class)).hasSize(2); - } - - @Test - public void register_class_with_classloader_and_fqcn() { - SpringComponentContainer container = new SimpleContainer(A.class, B.class); - container.startComponents(); - assertThat(container.context.getBeanDefinitionNames()) - .contains( - this.getClass().getClassLoader() + "-org.sonar.scanner.bootstrap.SpringComponentContainerTest.A", - this.getClass().getClassLoader() + "-org.sonar.scanner.bootstrap.SpringComponentContainerTest.B"); - assertThat(container.getComponentByType(A.class)).isNotNull(); - assertThat(container.getComponentByType(B.class)).isNotNull(); - } - - @Test - public void should_throw_start_exception_if_stop_also_throws_exception() { - ErrorStopClass errorStopClass = new ErrorStopClass(); - SpringComponentContainer container = new SpringComponentContainer() { - @Override - public void doBeforeStart() { - add(errorStopClass); - } - - @Override - public void doAfterStart() { - getComponentByType(ErrorStopClass.class); - throw new IllegalStateException("doBeforeStart"); - } - }; - assertThrows("doBeforeStart", IllegalStateException.class, container::execute); - assertThat(errorStopClass.stopped).isTrue(); - } - - @Test - public void should_support_extensions_without_annotations() { - SpringComponentContainer container = new SimpleContainer(A.class, B.class); - container.addExtension("", ExtensionWithMultipleConstructorsAndNoAnnotations.class); - container.startComponents(); - assertThat(container.getComponentByType(ExtensionWithMultipleConstructorsAndNoAnnotations.class).gotBothArgs).isTrue(); - } - - @Test - public void support_start_stop_callbacks() { - JsrLifecycleCallbacks jsr = new JsrLifecycleCallbacks(); - ApiStartable api = new ApiStartable(); - PicoStartable pico = new PicoStartable(); - - SpringComponentContainer container = new SimpleContainer(jsr, api, pico) { - @Override - public void doAfterStart() { - // force lazy instantiation - getComponentByType(JsrLifecycleCallbacks.class); - getComponentByType(ApiStartable.class); - getComponentByType(PicoStartable.class); - } - }; - container.execute(); - - assertThat(jsr.postConstruct).isTrue(); - assertThat(jsr.preDestroy).isTrue(); - assertThat(api.start).isTrue(); - assertThat(api.stop).isTrue(); - assertThat(pico.start).isTrue(); - assertThat(pico.stop).isTrue(); - } - - private static class JsrLifecycleCallbacks { - private boolean postConstruct = false; - private boolean preDestroy = false; - - @PostConstruct - public void postConstruct() { - postConstruct = true; - } - - @PreDestroy - public void preDestroy() { - preDestroy = true; - } - } - - private static class ApiStartable implements Startable { - private boolean start = false; - private boolean stop = false; - - public void start() { - start = true; - } - - public void stop() { - stop = true; - } - } - - private static class PicoStartable implements org.picocontainer.Startable { - private boolean start = false; - private boolean stop = false; - - public void start() { - start = true; - } - - public void stop() { - stop = true; - } - } - - private static class ToString { - private final String toString; - - public ToString(String toString) { - this.toString = toString; - } - - @Override - public String toString() { - return toString; - } - } - - private static class A { - } - - private static class B { - } - - private static class ExtensionWithMultipleConstructorsAndNoAnnotations { - private boolean gotBothArgs = false; - public ExtensionWithMultipleConstructorsAndNoAnnotations(A a) { - } - - public ExtensionWithMultipleConstructorsAndNoAnnotations(A a, B b) { - gotBothArgs = true; - } - } - - private static class ErrorStopClass implements Startable { - private boolean stopped = false; - - @Override - public void start() { - } - - @Override - public void stop() { - stopped = true; - throw new IllegalStateException("stop"); - } - } - - private static class SimpleContainer extends SpringComponentContainer { - public SimpleContainer(Object... objects) { - add(objects); - } - } -} 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 deleted file mode 100644 index ecdb6164cac..00000000000 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/StartableBeanPostProcessorTest.java +++ /dev/null @@ -1,64 +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 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/extension/ScannerCoreExtensionsInstallerTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/extension/ScannerCoreExtensionsInstallerTest.java index febb3323f5d..458d42dd691 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/extension/ScannerCoreExtensionsInstallerTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/extension/ScannerCoreExtensionsInstallerTest.java @@ -25,6 +25,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.stream.Stream; + import org.junit.Test; import org.sonar.api.SonarRuntime; import org.sonar.api.scanner.ScannerSide; @@ -32,7 +33,7 @@ import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.server.ServerSide; import org.sonar.core.extension.CoreExtension; import org.sonar.core.extension.CoreExtensionRepository; -import org.sonar.core.platform.ComponentContainer; +import org.sonar.core.platform.ListContainer; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -41,10 +42,9 @@ import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideF import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter; public class ScannerCoreExtensionsInstallerTest { - private SonarRuntime sonarRuntime = mock(SonarRuntime.class); - private CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class); - - private ScannerCoreExtensionsInstaller underTest = new ScannerCoreExtensionsInstaller(sonarRuntime, coreExtensionRepository); + private final SonarRuntime sonarRuntime = mock(SonarRuntime.class); + private final CoreExtensionRepository coreExtensionRepository = mock(CoreExtensionRepository.class); + private final ScannerCoreExtensionsInstaller underTest = new ScannerCoreExtensionsInstaller(sonarRuntime, coreExtensionRepository); @Test public void install_only_adds_ScannerSide_annotated_extension_to_container() { @@ -61,14 +61,13 @@ public class ScannerCoreExtensionsInstallerTest { NoAnnotationClass.class, OtherAnnotationClass.class, MultipleAnnotationClass.class); } })); - ComponentContainer container = new ComponentContainer(); + ListContainer container = new ListContainer(); underTest.install(container, noExtensionFilter(), noAdditionalSideFilter()); - assertThat(container.getPicoContainer().getComponentAdapters()) - .hasSize(ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2); - assertThat(container.getComponentByType(ScannerClass.class)).isNotNull(); - assertThat(container.getComponentByType(MultipleAnnotationClass.class)).isNotNull(); + assertThat(container.getAddedObjects()) + .hasSize(2) + .contains(ScannerClass.class, MultipleAnnotationClass.class); } @ComputeEngineSide 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 3f969ca4963..e0c3137f270 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,7 +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 org.springframework.beans.factory.BeanCreationException; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -44,7 +44,7 @@ public class NoLanguagesPluginsMediumTest { assertThatThrownBy(() -> tester .newAnalysis(new File(projectDir, "sonar-project.properties")) .execute()) - .isInstanceOf(UnsatisfiedDependencyException.class) + .isInstanceOf(BeanCreationException.class) .hasRootCauseMessage("No language plugins are installed."); } 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 ec873cf72ae..180466e355c 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 @@ -27,6 +27,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.fs.internal.DefaultInputModule; +import org.sonar.api.batch.fs.internal.DefaultInputProject; import org.sonar.scanner.fs.InputModuleHierarchy; import static org.assertj.core.api.Assertions.assertThat; @@ -34,46 +35,47 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class WorkDirectoriesInitializerTest { - private WorkDirectoriesInitializer initializer; + private final WorkDirectoriesInitializer initializer = new WorkDirectoriesInitializer(); + private final InputModuleHierarchy hierarchy = mock(InputModuleHierarchy.class); + private final DefaultInputProject project = mock(DefaultInputProject.class); + private final DefaultInputModule root = mock(DefaultInputModule.class); + @Rule public TemporaryFolder temp = new TemporaryFolder(); private File rootWorkDir; private File lock; - private InputModuleHierarchy hierarchy; - private DefaultInputModule root; @Before public void setUp() throws IOException { rootWorkDir = temp.newFolder(); - // create files to clean - new File(rootWorkDir, "foo.txt").createNewFile(); - File newFolder = new File(rootWorkDir, "foo"); + when(hierarchy.root()).thenReturn(root); + createFilesToClean(rootWorkDir); + when(root.getWorkDir()).thenReturn(rootWorkDir.toPath()); + when(project.getWorkDir()).thenReturn(rootWorkDir.toPath()); + } + + private void createFilesToClean(File dir) throws IOException { + new File(dir, "foo.txt").createNewFile(); + File newFolder = new File(dir, "foo"); newFolder.mkdir(); File fileInFolder = new File(newFolder, "test"); fileInFolder.createNewFile(); - lock = new File(rootWorkDir, DirectoryLock.LOCK_FILE_NAME); + lock = new File(dir, DirectoryLock.LOCK_FILE_NAME); lock.createNewFile(); - - hierarchy = mock(InputModuleHierarchy.class); - root = mock(DefaultInputModule.class); - when(hierarchy.root()).thenReturn(root); - when(root.getWorkDir()).thenReturn(rootWorkDir.toPath()); - - assertThat(rootWorkDir.list().length).isGreaterThan(1); - initializer = new WorkDirectoriesInitializer(); + assertThat(dir.list()).hasSizeGreaterThan(1); } @Test - public void testNonExisting() { + public void execute_doesnt_fail_if_nothing_to_clean() { temp.delete(); initializer.execute(hierarchy); } @Test - public void testClean() { - initializer.execute(hierarchy); + public void execute_should_clean_root() { + initializer.execute(project); assertThat(rootWorkDir).exists(); assertThat(lock).exists(); @@ -81,20 +83,35 @@ public class WorkDirectoriesInitializerTest { } @Test - public void cleaningRootModuleShouldNotDeleteChildrenWorkDir() throws IOException { + public void execute_on_hierarchy_should_clean_submodules() throws IOException { DefaultInputModule moduleA = mock(DefaultInputModule.class); + DefaultInputModule moduleB = mock(DefaultInputModule.class); + when(hierarchy.children(root)).thenReturn(Arrays.asList(moduleA)); + when(hierarchy.children(moduleA)).thenReturn(Arrays.asList(moduleB)); + File moduleAWorkdir = new File(rootWorkDir, "moduleA"); + File moduleBWorkdir = new File(moduleAWorkdir, "moduleB"); + when(moduleA.getWorkDir()).thenReturn(moduleAWorkdir.toPath()); + when(moduleB.getWorkDir()).thenReturn(moduleBWorkdir.toPath()); + moduleAWorkdir.mkdir(); + moduleBWorkdir.mkdir(); + new File(moduleAWorkdir, "fooA.txt").createNewFile(); + new File(moduleBWorkdir, "fooB.txt").createNewFile(); + initializer.execute(project); initializer.execute(hierarchy); assertThat(rootWorkDir).exists(); assertThat(lock).exists(); assertThat(rootWorkDir.list()).containsOnly(DirectoryLock.LOCK_FILE_NAME, "moduleA"); assertThat(moduleAWorkdir).exists(); + assertThat(moduleBWorkdir).exists(); + assertThat(moduleAWorkdir.list()).containsOnly("moduleB"); + assertThat(moduleBWorkdir).isEmptyDirectory(); } } |