aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core
diff options
context:
space:
mode:
authorsimonbrandhof <simon.brandhof@gmail.com>2010-09-28 12:10:05 +0000
committersimonbrandhof <simon.brandhof@gmail.com>2010-09-28 12:10:05 +0000
commitd2f25e344d5db20b68339d52ad940e7f17edfc4d (patch)
tree08764c4c16267bf9265f885859d65831c5d25332 /sonar-core
parent51f793f7e9f643e12d148a9fac9a2ac79ef3da49 (diff)
downloadsonarqube-d2f25e344d5db20b68339d52ad940e7f17edfc4d.tar.gz
sonarqube-d2f25e344d5db20b68339d52ad940e7f17edfc4d.zip
SONAR-1814 remove the API to find a plugin from an extension :
* do register coverage extensions in picocontainer only when the plugin is selected (see parameter sonar.core.codeCoveragePlugin) * do not display plugin names when detecting a duplication of metrics * remove unused methods from the deprecated component RulesManager
Diffstat (limited to 'sonar-core')
-rw-r--r--sonar-core/src/main/java/org/sonar/core/plugin/AbstractPluginRepository.java120
-rw-r--r--sonar-core/src/test/java/org/sonar/core/plugin/AbstractPluginRepositoryTest.java152
2 files changed, 272 insertions, 0 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/plugin/AbstractPluginRepository.java b/sonar-core/src/main/java/org/sonar/core/plugin/AbstractPluginRepository.java
new file mode 100644
index 00000000000..24a40d9fd68
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/plugin/AbstractPluginRepository.java
@@ -0,0 +1,120 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.core.plugin;
+
+import com.google.common.collect.Maps;
+import org.picocontainer.Characteristics;
+import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.injectors.ProviderAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.*;
+import org.sonar.api.platform.PluginRepository;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @since 2.2
+ */
+public abstract class AbstractPluginRepository implements PluginRepository {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractPluginRepository.class);
+
+ private Map<String, Plugin> pluginByKey = Maps.newHashMap();
+ private Map<Object, Plugin> pluginByExtension = Maps.newIdentityHashMap();
+
+ protected void registerPlugin(MutablePicoContainer container, Plugin plugin, String pluginKey) {
+ LOG.debug("Register the plugin {}", pluginKey);
+ pluginByKey.put(pluginKey, plugin);
+ for (Object extension : plugin.getExtensions()) {
+ registerExtension(container, plugin, pluginKey, extension);
+ }
+ }
+
+ private void registerExtension(MutablePicoContainer container, Plugin plugin, String pluginKey, Object extension) {
+ if (shouldRegisterExtension(pluginKey, extension)) {
+ LOG.debug("Register the extension: {}", extension);
+ container.as(Characteristics.CACHE).addComponent(getExtensionKey(extension), extension);
+ pluginByExtension.put(extension, plugin);
+ }
+ if (isExtensionProvider(extension)) {
+ LOG.debug("Register the extension provider: {}", extension);
+ container.as(Characteristics.CACHE).addAdapter(new ExtensionProviderAdapter(extension));
+ }
+ }
+
+ protected abstract boolean shouldRegisterExtension(String pluginKey, Object extension);
+
+ public Collection<Plugin> getPlugins() {
+ return pluginByKey.values();
+ }
+
+ public Plugin getPlugin(String key) {
+ return pluginByKey.get(key);
+ }
+
+ /**
+ * Returns the list of properties of a plugin
+ */
+ public Property[] getProperties(Plugin plugin) {
+ if (plugin != null) {
+ Class<? extends Plugin> classInstance = plugin.getClass();
+ if (classInstance.isAnnotationPresent(Properties.class)) {
+ return classInstance.getAnnotation(Properties.class).value();
+ }
+ }
+ return new Property[0];
+ }
+
+ public Property[] getProperties(String pluginKey) {
+ return getProperties(pluginByKey.get(pluginKey));
+ }
+
+ public Plugin getPluginForExtension(Object extension) {
+ Plugin plugin = pluginByExtension.get(extension);
+ if (plugin == null && !(extension instanceof Class)) {
+ plugin = pluginByExtension.get(extension.getClass());
+ }
+ return plugin;
+ }
+
+ protected static boolean isType(Object extension, Class<? extends Extension> extensionClass) {
+ Class clazz = (extension instanceof Class ? (Class) extension : extension.getClass());
+ return extensionClass.isAssignableFrom(clazz);
+ }
+
+ protected static boolean isExtensionProvider(Object extension) {
+ return extension instanceof ExtensionProvider;
+ }
+
+ protected static Object getExtensionKey(Object component) {
+ if (component instanceof Class) {
+ return component;
+ }
+ return component.getClass().getCanonicalName() + "-" + component.toString();
+ }
+
+ public static class ExtensionProviderAdapter extends ProviderAdapter {
+ public ExtensionProviderAdapter(Object provider) {
+ super(provider);
+ }
+ }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/plugin/AbstractPluginRepositoryTest.java b/sonar-core/src/test/java/org/sonar/core/plugin/AbstractPluginRepositoryTest.java
new file mode 100644
index 00000000000..319150c5c95
--- /dev/null
+++ b/sonar-core/src/test/java/org/sonar/core/plugin/AbstractPluginRepositoryTest.java
@@ -0,0 +1,152 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2009 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.core.plugin;
+
+import org.junit.Test;
+import org.picocontainer.MutablePicoContainer;
+import org.sonar.api.BatchExtension;
+import org.sonar.api.ExtensionProvider;
+import org.sonar.api.Plugin;
+import org.sonar.api.ServerExtension;
+import org.sonar.api.utils.IocContainer;
+
+import java.util.Arrays;
+
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class AbstractPluginRepositoryTest {
+
+ @Test
+ public void testIsType() {
+ assertThat(AbstractPluginRepository.isType(FakeServerExtension.class, ServerExtension.class), is(true));
+ assertThat(AbstractPluginRepository.isType(new FakeServerExtension(), ServerExtension.class), is(true));
+
+ assertThat(AbstractPluginRepository.isType(FakeBatchExtension.class, ServerExtension.class), is(false));
+ assertThat(AbstractPluginRepository.isType(new FakeBatchExtension(), ServerExtension.class), is(false));
+ assertThat(AbstractPluginRepository.isType(String.class, ServerExtension.class), is(false));
+ assertThat(AbstractPluginRepository.isType("foo", ServerExtension.class), is(false));
+ }
+
+ @Test
+ public void extensionKeyshouldBeClassNameIfClass() {
+ assertEquals(AbstractPluginRepository.getExtensionKey(FakeServerExtension.class), FakeServerExtension.class);
+ }
+
+ @Test
+ public void extensionKeyshouldBeUniqueIfObject() {
+ assertThat((String) AbstractPluginRepository.getExtensionKey(new FakeServerExtension()), endsWith("FakeServerExtension-instance"));
+ }
+
+ @Test
+ public void extensionProviderIsAnObjectButNotAClass() {
+ assertThat(AbstractPluginRepository.isExtensionProvider(BProvider.class), is(false));
+ assertThat(AbstractPluginRepository.isExtensionProvider(new BProvider()), is(true));
+ }
+
+ @Test
+ public void shouldRegisterExtensionProviders() {
+ MutablePicoContainer pico = IocContainer.buildPicoContainer();
+ AbstractPluginRepository repository = new AbstractPluginRepository() {
+ @Override
+ protected boolean shouldRegisterExtension(String pluginKey, Object extension) {
+ return isType(extension, ServerExtension.class);
+ }
+ };
+
+ Plugin plugin = mock(Plugin.class);
+ BProvider bProvider = new BProvider();
+ when(plugin.getExtensions()).thenReturn(Arrays.asList(A.class, bProvider, C.class, D.class));
+ repository.registerPlugin(pico, plugin, "foo");
+ pico.start();
+
+ assertThat(pico.getComponent(A.class), is(A.class));
+ assertThat(pico.getComponent(C.class), is(C.class));
+ assertThat(pico.getComponent(D.class), is(D.class));
+ assertThat(pico.getComponent(C.class).getBees().length, is(2));
+ assertThat(pico.getComponent(D.class).getBees().length, is(2));
+ assertThat(bProvider.calls, is(1)); // do not create B instances two times (C and D dependencies)
+
+ // Picocontainer question: why components created by providers are not registered in the container ?
+ //assertThat(pico.getComponents(B.class).size(), is(2)); // created by the ExtensionProvider
+ }
+
+ public static class FakeServerExtension implements ServerExtension {
+ @Override
+ public String toString() {
+ return "instance";
+ }
+ }
+
+ public static class FakeBatchExtension implements BatchExtension {
+
+ }
+
+ public static class A implements ServerExtension {
+ }
+
+ public static class B implements ServerExtension {
+ private A a;
+
+ public B(A a) {
+ this.a = a;
+ }
+ }
+
+ public static class C implements ServerExtension {
+ private B[] bees;
+
+ public C(B[] bees) {
+ this.bees = bees;
+ }
+
+ public B[] getBees() {
+ return bees;
+ }
+ }
+
+ public static class D implements ServerExtension {
+ private B[] bees;
+
+ public D(B[] bees) {
+ this.bees = bees;
+ }
+
+ public B[] getBees() {
+ return bees;
+ }
+ }
+
+ public static class BProvider extends ExtensionProvider {
+
+ private int calls = 0;
+ public B[] provide(A a) {
+ calls++;
+ return new B[]{new B(a), new B(a)};
+ }
+ }
+
+
+}