]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10690 Core Extension installed at level 1 2 3 and 4
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 14 Jun 2018 14:53:47 +0000 (16:53 +0200)
committerSonarTech <sonartech@sonarsource.com>
Thu, 21 Jun 2018 18:21:31 +0000 (20:21 +0200)
16 files changed:
server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
server/sonar-ce/src/test/java/org/sonar/ce/platform/CECoreExtensionsInstallerTest.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel2.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel3.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
server/sonar-server/src/test/java/org/sonar/server/platform/WebCoreExtensionsInstallerTest.java
sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsInstaller.java
sonar-core/src/main/java/org/sonar/core/extension/PlatformLevel.java
sonar-core/src/main/java/org/sonar/core/extension/PlatformLevelPredicates.java
sonar-core/src/test/java/org/sonar/core/extension/CoreExtensionsInstallerTest.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ModuleScanContainer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/task/TaskContainer.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/extension/ScannerCoreExtensionsInstallerTest.java

index a676084853127f9fec73bd81c1f94d2ef31cde88..061785baef511acd3fba3093094f69f17bbac9ea 100644 (file)
@@ -64,7 +64,6 @@ import org.sonar.ce.user.CeUserSession;
 import org.sonar.core.component.DefaultResourceTypes;
 import org.sonar.core.config.CorePropertyDefinitions;
 import org.sonar.core.extension.CoreExtensionRepositoryImpl;
-import org.sonar.core.extension.CoreExtensionsInstaller;
 import org.sonar.core.extension.CoreExtensionsLoader;
 import org.sonar.core.i18n.RuleI18nManager;
 import org.sonar.core.platform.ComponentContainer;
@@ -173,6 +172,9 @@ import org.sonar.server.webhook.WebhookModule;
 import org.sonarqube.ws.Rules;
 
 import static java.util.Objects.requireNonNull;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
+import static org.sonar.core.extension.PlatformLevelPredicates.hasPlatformLevel;
+import static org.sonar.core.extension.PlatformLevelPredicates.hasPlatformLevel4OrNone;
 import static org.sonar.process.ProcessProperties.Property.CLUSTER_ENABLED;
 
 public class ComputeEngineContainerImpl implements ComputeEngineContainer {
@@ -193,37 +195,64 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
     this.level1 = new ComponentContainer();
     populateLevel1(this.level1, props, requireNonNull(computeEngineStatus));
     configureFromModules(this.level1);
-    this.level1.startComponents();
+    startLevel1(this.level1);
 
     ComponentContainer level2 = this.level1.createChild();
     populateLevel2(level2);
     configureFromModules(level2);
-    level2.getComponentByType(CoreExtensionsLoader.class).load();
-    level2.startComponents();
+    startLevel2(level2);
 
     ComponentContainer level3 = level2.createChild();
     populateLevel3(level3);
     configureFromModules(level3);
-    level3.startComponents();
+    startLevel3(level3);
 
     this.level4 = level3.createChild();
     populateLevel4(this.level4, props);
-
     configureFromModules(this.level4);
-    CoreExtensionsInstaller coreExtensionsInstaller = this.level4.getComponentByType(CECoreExtensionsInstaller.class);
-    coreExtensionsInstaller.install(this.level4, t -> true);
-    ServerExtensionInstaller extensionInstaller = this.level4.getComponentByType(ServerExtensionInstaller.class);
-    extensionInstaller.installExtensions(this.level4);
-    this.level4.startComponents();
-    PlatformEditionProvider editionProvider = this.level4.getComponentByType(PlatformEditionProvider.class);
-    Loggers.get(ComputeEngineContainerImpl.class)
-      .info("Running {} edition", editionProvider.get().map(EditionProvider.Edition::getLabel).orElse(""));
+    startLevel4(this.level4);
 
     startupTasks();
 
     return this;
   }
 
+  private static void startLevel1(ComponentContainer level1) {
+    level1.getComponentByType(CoreExtensionsLoader.class)
+      .load();
+    level1.getComponentByType(CECoreExtensionsInstaller.class)
+      .install(level1, hasPlatformLevel(1), noAdditionalSideFilter());
+
+    level1.startComponents();
+  }
+
+  private static void startLevel2(ComponentContainer level2) {
+    level2.getComponentByType(CECoreExtensionsInstaller.class)
+      .install(level2, hasPlatformLevel(2), noAdditionalSideFilter());
+
+    level2.startComponents();
+  }
+
+  private static void startLevel3(ComponentContainer level3) {
+    level3.getComponentByType(CECoreExtensionsInstaller.class)
+      .install(level3, hasPlatformLevel(3), noAdditionalSideFilter());
+
+    level3.startComponents();
+  }
+
+  private static void startLevel4(ComponentContainer level4) {
+    level4.getComponentByType(CECoreExtensionsInstaller.class)
+      .install(level4, hasPlatformLevel4OrNone(), noAdditionalSideFilter());
+    level4.getComponentByType(ServerExtensionInstaller.class)
+      .installExtensions(level4);
+
+    level4.startComponents();
+
+    PlatformEditionProvider editionProvider = level4.getComponentByType(PlatformEditionProvider.class);
+    Loggers.get(ComputeEngineContainerImpl.class)
+      .info("Running {} edition", editionProvider.get().map(EditionProvider.Edition::getLabel).orElse(""));
+  }
+
   private void startupTasks() {
     ComponentContainer startupLevel = this.level4.createChild();
     startupLevel.add(startupComponents());
@@ -293,7 +322,11 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
       IssueIndex.class,
 
       new OkHttpClientProvider(),
-      computeEngineStatus);
+      computeEngineStatus,
+
+      CoreExtensionRepositoryImpl.class,
+      CoreExtensionsLoader.class,
+      CECoreExtensionsInstaller.class);
     container.add(toArray(CorePropertyDefinitions.all()));
   }
 
@@ -318,8 +351,6 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
       CePluginRepository.class,
       InstalledPluginReferentialFactory.class,
       ComputeEngineExtensionInstaller.class,
-      CoreExtensionRepositoryImpl.class,
-      CoreExtensionsLoader.class,
 
       // depends on plugins
       ServerI18n.class, // used by RuleI18nManager
@@ -442,7 +473,6 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
       PlatformEditionProvider.class,
 
       // privileged plugins
-      CECoreExtensionsInstaller.class,
       CoreExtensionBootstraper.class,
       CoreExtensionStopper.class,
 
index 9401436c0f859fbea59186935eac20dbf5bad6b8..0899d7f4c2b6903e8e54fc92b8f99a09fcb8a5a0 100644 (file)
@@ -94,7 +94,7 @@ public class ComputeEngineContainerImplTest {
       assertThat(picoContainer.getComponentAdapters())
         .hasSize(
           CONTAINER_ITSELF
-            + 85 // level 4
+            + 84 // level 4
             + 21 // content of QualityGateModule
             + 6 // content of CeConfigurationModule
             + 4 // content of CeQueueModule
@@ -113,12 +113,12 @@ public class ComputeEngineContainerImplTest {
       );
       assertThat(picoContainer.getParent().getParent().getComponentAdapters()).hasSize(
         CONTAINER_ITSELF
-          + 16 // MigrationConfigurationModule
+          + 14 // MigrationConfigurationModule
           + 19 // level 2
       );
       assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize(
         COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION
-          + 27 // level 1
+          + 30 // level 1
           + 55 // content of DaoModule
           + 3 // content of EsModule
           + 58 // content of CorePropertyDefinitions
index df075842c664a99eb6413b823ff82d89fda9e9cf..07938ee2cd33db8f2084dea8d52e79ec75693ef5 100644 (file)
@@ -37,6 +37,8 @@ import org.sonar.core.platform.ComponentContainer;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter;
 
 public class CECoreExtensionsInstallerTest {
   private SonarRuntime sonarRuntime = mock(SonarRuntime.class);
@@ -58,11 +60,10 @@ public class CECoreExtensionsInstallerTest {
           context.addExtensions(CeClass.class, ScannerClass.class, WebServerClass.class,
             NoAnnotationClass.class, OtherAnnotationClass.class, MultipleAnnotationClass.class);
         }
-      }
-    ));
+      }));
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     assertThat(container.getPicoContainer().getComponentAdapters())
       .hasSize(ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
index 6fed7e8b24529ac28ae2ca8dbdebbb736335634c..1b2276258e52aaa673052df002e553644f5e2ef6 100644 (file)
@@ -30,6 +30,8 @@ import org.sonar.api.utils.System2;
 import org.sonar.api.utils.Version;
 import org.sonar.api.utils.internal.TempFolderCleaner;
 import org.sonar.core.config.CorePropertyDefinitions;
+import org.sonar.core.extension.CoreExtensionRepositoryImpl;
+import org.sonar.core.extension.CoreExtensionsLoader;
 import org.sonar.core.util.UuidFactoryImpl;
 import org.sonar.db.DBSessionsImpl;
 import org.sonar.db.DaoModule;
@@ -51,6 +53,7 @@ import org.sonar.server.platform.Platform;
 import org.sonar.server.platform.ServerFileSystemImpl;
 import org.sonar.server.platform.TempFolderProvider;
 import org.sonar.server.platform.UrlSettings;
+import org.sonar.server.platform.WebCoreExtensionsInstaller;
 import org.sonar.server.platform.WebServerImpl;
 import org.sonar.server.platform.db.EmbeddedDatabaseFactory;
 import org.sonar.server.rule.index.RuleIndex;
@@ -59,6 +62,9 @@ import org.sonar.server.user.SystemPasscodeImpl;
 import org.sonar.server.user.ThreadLocalUserSession;
 import org.sonar.server.util.OkHttpClientProvider;
 
+import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
+import static org.sonar.core.extension.PlatformLevelPredicates.hasPlatformLevel;
+
 public class PlatformLevel1 extends PlatformLevel {
   private final Platform platform;
   private final Properties properties;
@@ -119,7 +125,11 @@ public class PlatformLevel1 extends PlatformLevel {
       // issues
       IssueIndex.class,
 
-      new OkHttpClientProvider());
+      new OkHttpClientProvider(),
+
+      CoreExtensionRepositoryImpl.class,
+      CoreExtensionsLoader.class,
+      WebCoreExtensionsInstaller.class);
     addAll(CorePropertyDefinitions.all());
 
     // cluster
@@ -133,4 +143,14 @@ public class PlatformLevel1 extends PlatformLevel {
       }
     }
   }
+
+  @Override
+  public PlatformLevel start() {
+    get(CoreExtensionsLoader.class)
+      .load();
+    get(WebCoreExtensionsInstaller.class)
+      .install(getContainer(), hasPlatformLevel(1), noAdditionalSideFilter());
+
+    return super.start();
+  }
 }
index 75d15421ba20e40016a16b98a558112926e9990b..f1c5a27b053a4c78e17bf7638df0f0caa698e9e3 100644 (file)
@@ -20,9 +20,9 @@
 package org.sonar.server.platform.platformlevel;
 
 import org.sonar.api.utils.Durations;
-import org.sonar.core.extension.CoreExtensionRepositoryImpl;
-import org.sonar.core.extension.CoreExtensionsLoader;
+import org.sonar.core.extension.CoreExtensionsInstaller;
 import org.sonar.core.i18n.RuleI18nManager;
+import org.sonar.core.platform.ComponentContainer;
 import org.sonar.core.platform.PluginClassloaderFactory;
 import org.sonar.core.platform.PluginLoader;
 import org.sonar.server.es.MigrationEsClientImpl;
@@ -30,6 +30,7 @@ import org.sonar.server.l18n.ServerI18n;
 import org.sonar.server.platform.DatabaseServerCompatibility;
 import org.sonar.server.platform.DefaultServerUpgradeStatus;
 import org.sonar.server.platform.StartupMetadataProvider;
+import org.sonar.server.platform.WebCoreExtensionsInstaller;
 import org.sonar.server.platform.db.CheckDatabaseCharsetAtStartup;
 import org.sonar.server.platform.db.migration.DatabaseMigrationExecutorServiceImpl;
 import org.sonar.server.platform.db.migration.DatabaseMigrationStateImpl;
@@ -46,6 +47,9 @@ import org.sonar.server.plugins.ServerPluginRepository;
 import org.sonar.server.plugins.WebServerExtensionInstaller;
 import org.sonar.server.startup.ClusterConfigurationCheck;
 
+import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
+import static org.sonar.core.extension.PlatformLevelPredicates.hasPlatformLevel;
+
 public class PlatformLevel2 extends PlatformLevel {
   public PlatformLevel2(PlatformLevel parent) {
     super("level2", parent);
@@ -74,8 +78,6 @@ public class PlatformLevel2 extends PlatformLevel {
       PluginClassloaderFactory.class,
       InstalledPluginReferentialFactory.class,
       WebServerExtensionInstaller.class,
-      CoreExtensionRepositoryImpl.class,
-      CoreExtensionsLoader.class,
 
       // depends on plugins
       ServerI18n.class,
@@ -89,8 +91,7 @@ public class PlatformLevel2 extends PlatformLevel {
       DatabaseMigrationExecutorServiceImpl.class);
 
     addIfCluster(
-      ClusterConfigurationCheck.class
-    );
+      ClusterConfigurationCheck.class);
 
     addIfStartupLeader(
       DatabaseCharsetChecker.class,
@@ -101,7 +102,11 @@ public class PlatformLevel2 extends PlatformLevel {
   public PlatformLevel start() {
     // ensuring the HistoryTable exists must be the first thing done when this level is started
     getOptional(MigrationHistoryTable.class).ifPresent(MigrationHistoryTable::start);
-    get(CoreExtensionsLoader.class).load();
+
+    ComponentContainer container = getContainer();
+    CoreExtensionsInstaller coreExtensionsInstaller = get(WebCoreExtensionsInstaller.class);
+    coreExtensionsInstaller.install(container, hasPlatformLevel(2), noAdditionalSideFilter());
+
     return super.start();
   }
 }
index 075f918ee02dc980b4fe160925d186e6197f02bb..27e8550d0a3e442fa3e0f75a8982c11c78f2e7ea 100644 (file)
@@ -20,6 +20,8 @@
 package org.sonar.server.platform.platformlevel;
 
 import org.sonar.api.utils.UriReader;
+import org.sonar.core.extension.CoreExtensionsInstaller;
+import org.sonar.core.platform.ComponentContainer;
 import org.sonar.core.util.DefaultHttpDownloader;
 import org.sonar.server.async.AsyncExecutionModule;
 import org.sonar.server.organization.DefaultOrganizationProviderImpl;
@@ -27,10 +29,14 @@ import org.sonar.server.organization.OrganizationFlagsImpl;
 import org.sonar.server.platform.ServerIdManager;
 import org.sonar.server.platform.ServerImpl;
 import org.sonar.server.platform.StartupMetadataPersister;
+import org.sonar.server.platform.WebCoreExtensionsInstaller;
 import org.sonar.server.platform.db.migration.NoopDatabaseMigrationImpl;
 import org.sonar.server.setting.DatabaseSettingLoader;
 import org.sonar.server.setting.DatabaseSettingsEnabler;
 
+import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
+import static org.sonar.core.extension.PlatformLevelPredicates.hasPlatformLevel;
+
 public class PlatformLevel3 extends PlatformLevel {
   public PlatformLevel3(PlatformLevel parent) {
     super("level3", parent);
@@ -51,4 +57,13 @@ public class PlatformLevel3 extends PlatformLevel {
       OrganizationFlagsImpl.class,
       AsyncExecutionModule.class);
   }
+
+  @Override
+  public PlatformLevel start() {
+    ComponentContainer container = getContainer();
+    CoreExtensionsInstaller coreExtensionsInstaller = get(WebCoreExtensionsInstaller.class);
+    coreExtensionsInstaller.install(container, hasPlatformLevel(3), noAdditionalSideFilter());
+
+    return super.start();
+  }
 }
index 306f7a36372a46d80dc57e3ce594198ea57c92f1..4cf3c4492d0728808e3fb8d533c8e39dd74aa565 100644 (file)
@@ -238,6 +238,9 @@ import org.sonar.server.ws.WebServiceFilter;
 import org.sonar.server.ws.WebServiceReroutingFilter;
 import org.sonar.server.ws.ws.WebServicesWsModule;
 
+import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
+import static org.sonar.core.extension.PlatformLevelPredicates.hasPlatformLevel4OrNone;
+
 public class PlatformLevel4 extends PlatformLevel {
 
   private final List<Object> level4AddedComponents;
@@ -536,7 +539,6 @@ public class PlatformLevel4 extends PlatformLevel {
       ProjectBadgesWsModule.class,
 
       // Core Extensions
-      WebCoreExtensionsInstaller.class,
       CoreExtensionBootstraper.class,
       CoreExtensionStopper.class,
 
@@ -581,7 +583,7 @@ public class PlatformLevel4 extends PlatformLevel {
   public PlatformLevel start() {
     ComponentContainer container = getContainer();
     CoreExtensionsInstaller coreExtensionsInstaller = get(WebCoreExtensionsInstaller.class);
-    coreExtensionsInstaller.install(container, t -> true);
+    coreExtensionsInstaller.install(container, hasPlatformLevel4OrNone(), noAdditionalSideFilter());
     ServerExtensionInstaller extensionInstaller = get(ServerExtensionInstaller.class);
     extensionInstaller.installExtensions(container);
 
index 60eee2cce4d41d57f19a12bbbb75bff59b320e62..b890aa29f807546e863f5fea0c6906d4a62c7389 100644 (file)
@@ -37,6 +37,8 @@ import org.sonar.core.platform.ComponentContainer;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter;
 
 public class WebCoreExtensionsInstallerTest {
   private SonarRuntime sonarRuntime = mock(SonarRuntime.class);
@@ -61,7 +63,7 @@ public class WebCoreExtensionsInstallerTest {
       }));
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     assertThat(container.getPicoContainer().getComponentAdapters())
       .hasSize(ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);
index a9b175f353e8fb6662f925e043cb7e6d7013275d..2e154769a55c6a46783a04c4566fac7e568161a7 100644 (file)
@@ -44,6 +44,14 @@ public abstract class CoreExtensionsInstaller {
   private final CoreExtensionRepository coreExtensionRepository;
   private final Class<? extends Annotation> supportedAnnotationType;
 
+  public static Predicate<Object> noExtensionFilter() {
+    return t -> true;
+  }
+
+  public static Predicate<Object> noAdditionalSideFilter() {
+    return t -> true;
+  }
+
   protected CoreExtensionsInstaller(SonarRuntime sonarRuntime, CoreExtensionRepository coreExtensionRepository,
     Class<? extends Annotation> supportedAnnotationType) {
     this.sonarRuntime = sonarRuntime;
@@ -51,18 +59,25 @@ public abstract class CoreExtensionsInstaller {
     this.supportedAnnotationType = supportedAnnotationType;
   }
 
-  public void install(ComponentContainer container, Predicate<Object> extensionFilter) {
+  /**
+   * @param container the container into which extensions will be installed
+   * @param extensionFilter filters extensions added to {@link CoreExtension.Context}. When it returns false, the
+   *                        extension is ignored as if it had never been added to the context.
+   * @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) {
     coreExtensionRepository.loadedCoreExtensions()
-      .forEach(coreExtension -> install(container, extensionFilter, coreExtension));
+      .forEach(coreExtension -> install(container, extensionFilter, additionalSideFilter, coreExtension));
   }
 
-  private void install(ComponentContainer container, Predicate<Object> extensionFilter, CoreExtension coreExtension) {
+  private void install(ComponentContainer container, Predicate<Object> extensionFilter, Predicate<Object> additionalSideFilter, CoreExtension coreExtension) {
     String coreExtensionName = coreExtension.getName();
     try {
-      List<Object> providerKeys = addDeclaredExtensions(container, extensionFilter, coreExtension);
-      addProvidedExtensions(container, extensionFilter, coreExtensionName, providerKeys);
+      List<Object> providerKeys = addDeclaredExtensions(container, extensionFilter, additionalSideFilter, coreExtension);
+      addProvidedExtensions(container, additionalSideFilter, coreExtensionName, providerKeys);
 
-      LOG.info("Installed core extension: " + coreExtensionName);
+      LOG.debug("Installed core extension: " + coreExtensionName);
       coreExtensionRepository.installed(coreExtension);
     } catch (Exception e) {
       throw new RuntimeException("Failed to load core extension " + coreExtensionName, e);
@@ -70,36 +85,36 @@ public abstract class CoreExtensionsInstaller {
   }
 
   private List<Object> addDeclaredExtensions(ComponentContainer container, Predicate<Object> extensionFilter,
-    CoreExtension coreExtension) {
-    ContextImpl context = new ContextImpl(container, extensionFilter, coreExtension.getName());
+    Predicate<Object> additionalSideFilter, CoreExtension coreExtension) {
+    ContextImpl context = new ContextImpl(container, extensionFilter, additionalSideFilter, coreExtension.getName());
     coreExtension.load(context);
     return context.getProviders();
   }
 
-  private void addProvidedExtensions(ComponentContainer container, Predicate<Object> extensionFilter,
+  private void addProvidedExtensions(ComponentContainer container, Predicate<Object> additionalSideFilter,
     String extensionCategory, List<Object> providerKeys) {
     providerKeys.stream()
       .map(providerKey -> (ExtensionProvider) container.getComponentByKey(providerKey))
-      .forEach(provider -> addFromProvider(container, extensionFilter, extensionCategory, provider));
+      .forEach(provider -> addFromProvider(container, additionalSideFilter, extensionCategory, provider));
   }
 
-  private void addFromProvider(ComponentContainer container, Predicate<Object> extensionFilter,
+  private void addFromProvider(ComponentContainer container, Predicate<Object> additionalSideFilter,
     String extensionCategory, ExtensionProvider provider) {
     Object obj = provider.provide();
     if (obj != null) {
       if (obj instanceof Iterable) {
         for (Object ext : (Iterable) obj) {
-          addSupportedExtension(container, extensionFilter, extensionCategory, ext);
+          addSupportedExtension(container, additionalSideFilter, extensionCategory, ext);
         }
       } else {
-        addSupportedExtension(container, extensionFilter, extensionCategory, obj);
+        addSupportedExtension(container, additionalSideFilter, extensionCategory, obj);
       }
     }
   }
 
-  private <T> boolean addSupportedExtension(ComponentContainer container, Predicate<Object> extensionFilter,
+  private <T> boolean addSupportedExtension(ComponentContainer container, Predicate<Object> additionalSideFilter,
     String extensionCategory, T component) {
-    if (hasSupportedAnnotation(component) && extensionFilter.test(component)) {
+    if (hasSupportedAnnotation(component) && additionalSideFilter.test(component)) {
       container.addExtension(extensionCategory, component);
       return true;
     }
@@ -113,12 +128,15 @@ public abstract class CoreExtensionsInstaller {
   private class ContextImpl implements CoreExtension.Context {
     private final ComponentContainer container;
     private final Predicate<Object> extensionFilter;
+    private final Predicate<Object> additionalSideFilter;
     private final String extensionCategory;
     private final List<Object> providers = new ArrayList<>();
 
-    public ContextImpl(ComponentContainer container, Predicate<Object> extensionFilter, String extensionCategory) {
+    public ContextImpl(ComponentContainer container, Predicate<Object> extensionFilter,
+      Predicate<Object> additionalSideFilter, String extensionCategory) {
       this.container = container;
       this.extensionFilter = extensionFilter;
+      this.additionalSideFilter = additionalSideFilter;
       this.extensionCategory = extensionCategory;
     }
 
@@ -136,8 +154,11 @@ public abstract class CoreExtensionsInstaller {
     @Override
     public CoreExtension.Context addExtension(Object component) {
       requireNonNull(component, "component can't be null");
+      if (!extensionFilter.test(component)) {
+        return this;
+      }
 
-      if (!addSupportedExtension(container, extensionFilter, extensionCategory, component)) {
+      if (!addSupportedExtension(container, additionalSideFilter, extensionCategory, component)) {
         container.declareExtension(extensionCategory, component);
       } else if (ExtensionProviderSupport.isExtensionProvider(component)) {
         providers.add(component);
index 6396deac9fe8a6af13883b7c0f45a09080db60f6..60f81b16324a9b51a6d7454752ec4f2f15e61ffd 100644 (file)
@@ -1,3 +1,22 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.extension;
 
 import java.lang.annotation.Documented;
@@ -10,5 +29,8 @@ import java.lang.annotation.Target;
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE)
 public @interface PlatformLevel {
+  /**
+   * Supported values are: 1, 2, 3 and 4.
+   */
   int value() default 4;
 }
index bda0f9cfcbc65ce75100a4ba7a7205fadd98d194..c3f5479b17c1a97bc2a09d1a157b49df680a7e84 100644 (file)
@@ -1,4 +1,68 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.extension;
 
-public class PlatformLevelPredicates {
+import java.util.function.Predicate;
+import javax.annotation.Nullable;
+import org.sonar.api.utils.AnnotationUtils;
+
+public final class PlatformLevelPredicates {
+  private PlatformLevelPredicates() {
+    // prevents instantiation
+  }
+
+  public static Predicate<Object> hasPlatformLevel(int i) {
+    checkSupportedLevel(i, null);
+    return o -> {
+      PlatformLevel platformLevel = AnnotationUtils.getAnnotation(o, PlatformLevel.class);
+      return platformLevel != null && checkSupportedLevel(platformLevel.value(), o) == i;
+    };
+  }
+
+  private static int checkSupportedLevel(int i, @Nullable Object annotatedObject) {
+    boolean supported = i >= 1 && i <= 4;
+    if (supported) {
+      return i;
+    }
+
+    throw new IllegalArgumentException(buildErrorMsgFrom(annotatedObject));
+  }
+
+  private static String buildErrorMsgFrom(@Nullable Object annotatedObject) {
+    String baseErrorMsg = "Only level 1, 2, 3 and 4 are supported";
+    if (annotatedObject == null) {
+      return baseErrorMsg;
+    } else if (annotatedObject instanceof Class) {
+      return String.format("Invalid value for annotation %s on class '%s'. %s",
+        PlatformLevel.class.getName(), ((Class) annotatedObject).getName(),
+        baseErrorMsg);
+    } else {
+      return String.format("Invalid value for annotation %s on object of type %s. %s",
+        PlatformLevel.class.getName(), annotatedObject.getClass().getName(), baseErrorMsg);
+    }
+  }
+
+  public static Predicate<Object> hasPlatformLevel4OrNone() {
+    return o -> {
+      PlatformLevel platformLevel = AnnotationUtils.getAnnotation(o, PlatformLevel.class);
+      return platformLevel == null || checkSupportedLevel(platformLevel.value(), o) == 4;
+    };
+  }
 }
index d9d03370863000eed25e8110fb8ab25a16e46210..aa63f2a0d32e8bf735c25a7d52846ba195acdf9e 100644 (file)
@@ -55,6 +55,8 @@ import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter;
 import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
 
 @RunWith(DataProviderRunner.class)
@@ -72,7 +74,7 @@ public class CoreExtensionsInstallerTest {
   public void install_has_no_effect_if_CoreExtensionRepository_has_no_loaded_CoreExtension() {
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     assertAddedExtensions(container, 0);
   }
@@ -88,7 +90,7 @@ public class CoreExtensionsInstallerTest {
     when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(coreExtensions.stream());
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     inOrder.verify(coreExtension1).load(contextCaptor.capture());
     inOrder.verify(coreExtension2).load(contextCaptor.capture());
@@ -106,7 +108,7 @@ public class CoreExtensionsInstallerTest {
     when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension1, coreExtension2));
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     verify(coreExtension1).load(contextCaptor.capture());
     verify(coreExtension2).load(contextCaptor.capture());
@@ -122,7 +124,7 @@ public class CoreExtensionsInstallerTest {
     when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension1, coreExtension2));
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     verify(coreExtension1).load(contextCaptor.capture());
     verify(coreExtension2).load(contextCaptor.capture());
@@ -140,7 +142,7 @@ public class CoreExtensionsInstallerTest {
     ComponentContainer container = new ComponentContainer();
     container.add(configuration);
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     verify(coreExtension1).load(contextCaptor.capture());
     verify(coreExtension2).load(contextCaptor.capture());
@@ -157,7 +159,7 @@ public class CoreExtensionsInstallerTest {
     when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     assertAddedExtensions(container, WestSideClass.class, Latitude.class);
     assertPropertyDefinitions(container);
@@ -171,7 +173,7 @@ public class CoreExtensionsInstallerTest {
     when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> t != Latitude.class);
+    underTest.install(container, noExtensionFilter(), t -> t != Latitude.class);
 
     assertAddedExtensions(container, WestSideClass.class);
     assertPropertyDefinitions(container);
@@ -186,7 +188,7 @@ public class CoreExtensionsInstallerTest {
     when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     assertAddedExtensions(container, WestSidePropertyDefinition.class, LatitudePropertyDefinition.class);
     assertPropertyDefinitions(container, "westKey", "eastKey", "otherKey", "latitudeKey", "blankKey");
@@ -201,7 +203,7 @@ public class CoreExtensionsInstallerTest {
     when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> false);
+    underTest.install(container, noExtensionFilter(), t -> false);
 
     assertAddedExtensions(container, 0);
     assertPropertyDefinitions(container, "westKey", "eastKey", "otherKey", "latitudeKey", "blankKey");
@@ -217,7 +219,7 @@ public class CoreExtensionsInstallerTest {
     when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     assertAddedExtensions(container, 0);
     assertPropertyDefinitions(container, coreExtension, propertyDefinitionNoCategory, propertyDefinitionWithCategory);
@@ -231,7 +233,7 @@ public class CoreExtensionsInstallerTest {
     when(coreExtensionRepository.loadedCoreExtensions()).thenReturn(Stream.of(coreExtension));
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     assertAddedExtensions(container, WestSideProvider.class, WestSideProvided.class, PartiallyWestSideProvider.class);
     assertPropertyDefinitions(container);
index 2d55e97cd1a0cc844cf0ea113adc1b8e8647873e..55a02047280972fd3ca65154c2c8fea6a41259c2 100644 (file)
@@ -73,6 +73,7 @@ import org.sonar.scanner.source.HighlightableBuilder;
 import org.sonar.scanner.source.SymbolizableBuilder;
 
 import static org.sonar.api.batch.InstantiationStrategy.PER_PROJECT;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter;
 import static org.sonar.scanner.bootstrap.ExtensionUtils.isInstantiationStrategy;
 import static org.sonar.scanner.bootstrap.ExtensionUtils.isScannerSide;
 
@@ -169,7 +170,7 @@ public class ModuleScanContainer extends ComponentContainer {
 
   private void addExtensions() {
     CoreExtensionsInstaller coreExtensionsInstaller = getComponentByType(CoreExtensionsInstaller.class);
-    coreExtensionsInstaller.install(this, t -> isInstantiationStrategy(t, PER_PROJECT));
+    coreExtensionsInstaller.install(this, noExtensionFilter(), t -> isInstantiationStrategy(t, PER_PROJECT));
     ExtensionInstaller pluginInstaller = getComponentByType(ExtensionInstaller.class);
     pluginInstaller.install(this, e -> isScannerSide(e) && isInstantiationStrategy(e, PER_PROJECT));
   }
index 1ed39274ebad2c513f1843bd26c788461f28aae0..1fc6984136cce28fdabd7b19ee7239e42201a7ec 100644 (file)
@@ -102,6 +102,7 @@ import org.sonar.scanner.scm.ScmChangedFilesProvider;
 import org.sonar.scanner.storage.Storages;
 
 import static org.sonar.api.batch.InstantiationStrategy.PER_BATCH;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter;
 import static org.sonar.scanner.bootstrap.ExtensionUtils.isInstantiationStrategy;
 import static org.sonar.scanner.bootstrap.ExtensionUtils.isScannerSide;
 
@@ -242,7 +243,7 @@ public class ProjectScanContainer extends ComponentContainer {
 
   private void addBatchExtensions() {
     getComponentByType(CoreExtensionsInstaller.class)
-      .install(this, extension -> isInstantiationStrategy(extension, PER_BATCH));
+      .install(this, noExtensionFilter(), extension -> isInstantiationStrategy(extension, PER_BATCH));
     getComponentByType(ExtensionInstaller.class)
       .install(this, getBatchPluginExtensionsFilter());
   }
index 1d0c943aef1d77cb34dd1863f7993c78575b3164..3338e8e823a9b1c782d6eb34b6eeca5be808866a 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.scanner.bootstrap.ExtensionInstaller;
 import org.sonar.scanner.bootstrap.GlobalProperties;
 
 import static org.sonar.api.batch.InstantiationStrategy.PER_TASK;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter;
 import static org.sonar.scanner.bootstrap.ExtensionUtils.isInstantiationStrategy;
 import static org.sonar.scanner.bootstrap.ExtensionUtils.isScannerSide;
 
@@ -60,7 +61,7 @@ public class TaskContainer extends ComponentContainer {
 
   private void addTaskExtensions() {
     getComponentByType(CoreExtensionsInstaller.class)
-      .install(this, t -> isInstantiationStrategy(t, PER_TASK));
+      .install(this, noExtensionFilter(), t -> isInstantiationStrategy(t, PER_TASK));
     getComponentByType(ExtensionInstaller.class)
       .install(this, extension -> isScannerSide(extension) && isInstantiationStrategy(extension, PER_TASK));
   }
index a359ba309676c43625ea73a7817f08ece03da46c..ef8e27eba676d72898588fd5d0bc55fa39fcea44 100644 (file)
@@ -37,6 +37,8 @@ import org.sonar.core.platform.ComponentContainer;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
+import static org.sonar.core.extension.CoreExtensionsInstaller.noExtensionFilter;
 
 public class ScannerCoreExtensionsInstallerTest {
   private SonarRuntime sonarRuntime = mock(SonarRuntime.class);
@@ -61,7 +63,7 @@ public class ScannerCoreExtensionsInstallerTest {
       }));
     ComponentContainer container = new ComponentContainer();
 
-    underTest.install(container, t -> true);
+    underTest.install(container, noExtensionFilter(), noAdditionalSideFilter());
 
     assertThat(container.getPicoContainer().getComponentAdapters())
       .hasSize(ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 2);