diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2018-06-14 16:53:47 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-06-21 20:21:31 +0200 |
commit | b1ee6a846be4e4a48ec4cdc5841ca53886c029f9 (patch) | |
tree | 233bc7c1657ab70e6de9e1ce6ccfcaf5dfcb2f0e /sonar-core | |
parent | 81a06e86f6aab48131591675ccc0dd54261c0e4f (diff) | |
download | sonarqube-b1ee6a846be4e4a48ec4cdc5841ca53886c029f9.tar.gz sonarqube-b1ee6a846be4e4a48ec4cdc5841ca53886c029f9.zip |
SONAR-10690 Core Extension installed at level 1 2 3 and 4
Diffstat (limited to 'sonar-core')
4 files changed, 138 insertions, 29 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsInstaller.java b/sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsInstaller.java index a9b175f353e..2e154769a55 100644 --- a/sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsInstaller.java +++ b/sonar-core/src/main/java/org/sonar/core/extension/CoreExtensionsInstaller.java @@ -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); diff --git a/sonar-core/src/main/java/org/sonar/core/extension/PlatformLevel.java b/sonar-core/src/main/java/org/sonar/core/extension/PlatformLevel.java index 6396deac9fe..60f81b16324 100644 --- a/sonar-core/src/main/java/org/sonar/core/extension/PlatformLevel.java +++ b/sonar-core/src/main/java/org/sonar/core/extension/PlatformLevel.java @@ -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; } diff --git a/sonar-core/src/main/java/org/sonar/core/extension/PlatformLevelPredicates.java b/sonar-core/src/main/java/org/sonar/core/extension/PlatformLevelPredicates.java index bda0f9cfcbc..c3f5479b17c 100644 --- a/sonar-core/src/main/java/org/sonar/core/extension/PlatformLevelPredicates.java +++ b/sonar-core/src/main/java/org/sonar/core/extension/PlatformLevelPredicates.java @@ -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; + }; + } } diff --git a/sonar-core/src/test/java/org/sonar/core/extension/CoreExtensionsInstallerTest.java b/sonar-core/src/test/java/org/sonar/core/extension/CoreExtensionsInstallerTest.java index d9d03370863..aa63f2a0d32 100644 --- a/sonar-core/src/test/java/org/sonar/core/extension/CoreExtensionsInstallerTest.java +++ b/sonar-core/src/test/java/org/sonar/core/extension/CoreExtensionsInstallerTest.java @@ -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); |