aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-plugin-api
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2015-04-24 09:15:05 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2015-05-11 10:21:55 +0200
commit14a5c982e5f1b28354a853073bd3e225b3914abe (patch)
treee298a2948f49628880f8d5290451adc14a920613 /sonar-plugin-api
parentcba928d505985972e13c8e895b490a52702af925 (diff)
downloadsonarqube-14a5c982e5f1b28354a853073bd3e225b3914abe.tar.gz
sonarqube-14a5c982e5f1b28354a853073bd3e225b3914abe.zip
SONAR-6370 isolate plugin classloader from core
Diffstat (limited to 'sonar-plugin-api')
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java253
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentKeys.java57
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/platform/PicoUtils.java46
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginMetadata.java74
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginRepository.java48
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/platform/ComponentContainerTest.java390
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/platform/ComponentKeysTest.java77
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/platform/PicoUtilsTest.java106
9 files changed, 1 insertions, 1052 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java b/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java
index ea7bbc755e9..23f5021d3fb 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java
@@ -24,9 +24,9 @@ import java.util.List;
/**
* A plugin is a group of extensions. See <code>org.sonar.api.Extension</code> interface to browse
* available extension points.
- * <p/>
* <p>The manifest property <code>Plugin-Class</code> must declare the name of the implementation class.
* It is automatically set by sonar-packaging-maven-plugin when building plugins.</p>
+ * <p>Implementation must declare a public constructor with no-parameters.</p>
*
* @see org.sonar.api.Extension
* @since 1.10
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java
deleted file mode 100644
index e8555ed4e35..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.platform;
-
-import com.google.common.collect.Iterables;
-import org.picocontainer.Characteristics;
-import org.picocontainer.ComponentAdapter;
-import org.picocontainer.DefaultPicoContainer;
-import org.picocontainer.MutablePicoContainer;
-import org.picocontainer.behaviors.OptInCaching;
-import org.picocontainer.lifecycle.ReflectionLifecycleStrategy;
-import org.picocontainer.monitors.NullComponentMonitor;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.ServerComponent;
-import org.sonar.api.config.PropertyDefinitions;
-
-import javax.annotation.Nullable;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * @since 2.12
- */
-public class ComponentContainer implements BatchComponent, ServerComponent {
-
- // no need for multiple children
- ComponentContainer parent, child;
- MutablePicoContainer pico;
- PropertyDefinitions propertyDefinitions;
- ComponentKeys componentKeys;
-
- /**
- * Create root container
- */
- public ComponentContainer() {
- this.parent = null;
- this.child = null;
- this.pico = createPicoContainer();
- this.componentKeys = new ComponentKeys();
- propertyDefinitions = new PropertyDefinitions();
- addSingleton(propertyDefinitions);
- addSingleton(this);
- }
-
- /**
- * Create child container
- */
- protected ComponentContainer(ComponentContainer parent) {
- this.parent = parent;
- this.pico = parent.pico.makeChildContainer();
- this.parent.child = this;
- this.propertyDefinitions = parent.propertyDefinitions;
- this.componentKeys = new ComponentKeys();
- addSingleton(this);
- }
-
- public void execute() {
- boolean threw = true;
- try {
- startComponents();
- threw = false;
- } finally {
- stopComponents(threw);
- }
- }
-
- /**
- * This method MUST NOT be renamed start() because the container is registered itself in picocontainer. Starting
- * a component twice is not authorized.
- */
- public ComponentContainer startComponents() {
- try {
- doBeforeStart();
- pico.start();
- doAfterStart();
- return this;
- } catch (Exception e) {
- throw PicoUtils.propagate(e);
- }
- }
-
- /**
- * This method aims to be overridden
- */
- protected void doBeforeStart() {
- // nothing
- }
-
- /**
- * This method aims to be overridden
- */
- protected void doAfterStart() {
- // nothing
- }
-
- /**
- * This method MUST NOT be renamed stop() because the container is registered itself in picocontainer. Starting
- * a component twice is not authorized.
- */
- public ComponentContainer stopComponents() {
- return stopComponents(false);
- }
-
- public ComponentContainer stopComponents(boolean swallowException) {
- try {
- pico.stop();
- pico.dispose();
-
- } catch (RuntimeException e) {
- if (!swallowException) {
- throw PicoUtils.propagate(e);
- }
- } finally {
- removeChild();
- if (parent != null) {
- parent.removeChild();
- }
- }
- return this;
- }
-
- /**
- * @since 3.5
- */
- public ComponentContainer add(Object... objects) {
- for (Object object : objects) {
- if (object instanceof ComponentAdapter) {
- addPicoAdapter((ComponentAdapter) object);
- } else if (object instanceof Iterable) {
- add(Iterables.toArray((Iterable) object, Object.class));
- } else {
- addSingleton(object);
- }
- }
- return this;
- }
-
- public ComponentContainer addSingletons(Collection components) {
- for (Object component : components) {
- addSingleton(component);
- }
- return this;
- }
-
- public ComponentContainer addSingleton(Object component) {
- return addComponent(component, true);
- }
-
- /**
- * @param singleton return always the same instance if true, else a new instance
- * is returned each time the component is requested
- */
- public ComponentContainer addComponent(Object component, boolean singleton) {
- Object key = componentKeys.of(component);
- if (component instanceof ComponentAdapter) {
- pico.addAdapter((ComponentAdapter) component);
- } else {
- try {
- pico.as(singleton ? Characteristics.CACHE : Characteristics.NO_CACHE).addComponent(key, component);
- } catch (Throwable t) {
- throw new IllegalStateException("Unable to register component " + getName(component), t);
- }
- declareExtension(null, component);
- }
- return this;
- }
-
- public ComponentContainer addExtension(@Nullable PluginMetadata plugin, Object extension) {
- Object key = componentKeys.of(extension);
- try {
- pico.as(Characteristics.CACHE).addComponent(key, extension);
- } catch (Throwable t) {
- throw new IllegalStateException("Unable to register extension " + getName(extension), t);
- }
- declareExtension(plugin, extension);
- return this;
- }
-
- private String getName(Object extension) {
- if (extension instanceof Class) {
- return ((Class) extension).getName();
- }
- return getName(extension.getClass());
- }
-
- public void declareExtension(@Nullable PluginMetadata plugin, Object extension) {
- propertyDefinitions.addComponent(extension, plugin != null ? plugin.getName() : "");
- }
-
- public ComponentContainer addPicoAdapter(ComponentAdapter adapter) {
- pico.addAdapter(adapter);
- return this;
- }
-
- public <T> T getComponentByType(Class<T> tClass) {
- return pico.getComponent(tClass);
- }
-
- public Object getComponentByKey(Object key) {
- return pico.getComponent(key);
- }
-
- public <T> List<T> getComponentsByType(Class<T> tClass) {
- return pico.getComponents(tClass);
- }
-
- public ComponentContainer removeChild() {
- if (child != null) {
- pico.removeChildContainer(child.pico);
- child = null;
- }
- return this;
- }
-
- public ComponentContainer createChild() {
- return new ComponentContainer(this);
- }
-
- static MutablePicoContainer createPicoContainer() {
- ReflectionLifecycleStrategy lifecycleStrategy = new ReflectionLifecycleStrategy(new NullComponentMonitor(), "start", "stop", "close");
- return new DefaultPicoContainer(new OptInCaching(), lifecycleStrategy, null);
- }
-
- public ComponentContainer getParent() {
- return parent;
- }
-
- public ComponentContainer getChild() {
- return child;
- }
-
- public MutablePicoContainer getPicoContainer() {
- return pico;
- }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentKeys.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentKeys.java
deleted file mode 100644
index 56de51f17e1..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentKeys.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.platform;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.sonar.api.utils.internal.Uuids;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-/**
- * @since 3.7.1
- */
-class ComponentKeys {
-
- private static final Pattern IDENTITY_HASH_PATTERN = Pattern.compile(".+@[a-f0-9]+");
- private final Set<Class> objectsWithoutToString = new HashSet<Class>();
-
- Object of(Object component) {
- return of(component, Loggers.get(ComponentKeys.class));
- }
-
- @VisibleForTesting
- Object of(Object component, Logger log) {
- if (component instanceof Class) {
- return component;
- }
- String key = component.toString();
- if (IDENTITY_HASH_PATTERN.matcher(key).matches()) {
- if (!objectsWithoutToString.add(component.getClass())) {
- log.warn(String.format("Bad component key: %s. Please implement toString() method on class %s", key, component.getClass().getName()));
- }
- key += Uuids.create();
- }
- return new StringBuilder().append(component.getClass().getCanonicalName()).append("-").append(key).toString();
- }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/PicoUtils.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/PicoUtils.java
deleted file mode 100644
index b14d886196b..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/platform/PicoUtils.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.platform;
-
-import com.google.common.base.Throwables;
-import org.picocontainer.PicoLifecycleException;
-
-class PicoUtils {
-
- private PicoUtils() {
- }
-
- static Throwable sanitize(Throwable t) {
- Throwable result = t;
- Throwable cause = t.getCause();
- if (t instanceof PicoLifecycleException && cause != null) {
- if ("wrapper".equals(cause.getMessage()) && cause.getCause() != null) {
- result = cause.getCause();
- } else {
- result = cause;
- }
- }
- return result;
- }
-
- static RuntimeException propagate(Throwable t) {
- throw Throwables.propagate(sanitize(t));
- }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginMetadata.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginMetadata.java
deleted file mode 100644
index 97ab71bcfc1..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginMetadata.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.platform;
-
-import javax.annotation.CheckForNull;
-import java.io.File;
-import java.util.List;
-
-/**
- * @since 2.8
- */
-public interface PluginMetadata {
- File getFile();
-
- List<File> getDeployedFiles();
-
- String getKey();
-
- String getName();
-
- String getMainClass();
-
- String getDescription();
-
- String getOrganization();
-
- String getOrganizationUrl();
-
- String getLicense();
-
- String getVersion();
-
- String getHomepage();
-
- /**
- * @since 3.6
- */
- String getIssueTrackerUrl();
-
- boolean isUseChildFirstClassLoader();
-
- String getBasePlugin();
-
- /**
- * Always return <code>null</code> since version 5.2
- * @deprecated in 5.2. Concept of parent relationship is removed. See https://jira.codehaus.org/browse/SONAR-6433
- */
- @Deprecated
- @CheckForNull
- String getParent();
-
- List<String> getRequiredPlugins();
-
- boolean isCore();
-
- String getImplementationBuild();
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginRepository.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginRepository.java
deleted file mode 100644
index ad26ec2dae3..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginRepository.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.platform;
-
-import org.sonar.api.BatchComponent;
-import org.sonar.api.Plugin;
-import org.sonar.api.ServerComponent;
-
-import javax.annotation.CheckForNull;
-import java.util.Collection;
-
-public interface PluginRepository extends BatchComponent, ServerComponent {
- @CheckForNull
- Plugin getPlugin(String key);
-
- /**
- * Metadata of installed plugins. Metadata includes all the fields available in update center
- * (plugin key, name, version, description, license, ...) and some technical information like
- * list of embedded libraries and classloader strategy.
- *
- * @since 2.9
- */
- Collection<PluginMetadata> getMetadata();
-
- /**
- * Search for an installed plugin. Returns null if the plugin is not installed.
- * @since 2.9
- */
- @CheckForNull
- PluginMetadata getMetadata(String pluginKey);
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/platform/ComponentContainerTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/platform/ComponentContainerTest.java
deleted file mode 100644
index 8cbe1f5d3b4..00000000000
--- a/sonar-plugin-api/src/test/java/org/sonar/api/platform/ComponentContainerTest.java
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.platform;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.picocontainer.injectors.ProviderAdapter;
-import org.sonar.api.Property;
-import org.sonar.api.config.PropertyDefinitions;
-
-import java.util.Arrays;
-
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.*;
-
-public class ComponentContainerTest {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- @Test
- public void shouldRegisterItself() {
- ComponentContainer container = new ComponentContainer();
- assertThat(container.getComponentByType(ComponentContainer.class)).isSameAs(container);
- }
-
- @Test
- public void should_start_and_stop() {
- ComponentContainer container = spy(new ComponentContainer());
- container.addSingleton(StartableComponent.class);
- container.startComponents();
-
- assertThat(container.getComponentByType(StartableComponent.class).started).isTrue();
- assertThat(container.getComponentByType(StartableComponent.class).stopped).isFalse();
- verify(container).doBeforeStart();
- verify(container).doAfterStart();
-
- container.stopComponents();
- assertThat(container.getComponentByType(StartableComponent.class).stopped).isTrue();
- }
-
- @Test
- public void should_start_and_stop_hierarchy_of_containers() {
- StartableComponent parentComponent = new StartableComponent();
- final StartableComponent childComponent = new StartableComponent();
- ComponentContainer parentContainer = new ComponentContainer() {
- @Override
- public void doAfterStart() {
- ComponentContainer childContainer = new ComponentContainer(this);
- childContainer.add(childComponent);
- childContainer.execute();
- }
- };
- parentContainer.add(parentComponent);
- parentContainer.execute();
- assertThat(parentComponent.started).isTrue();
- assertThat(parentComponent.stopped).isTrue();
- assertThat(childComponent.started).isTrue();
- assertThat(childComponent.stopped).isTrue();
- }
-
- @Test
- public void should_stop_hierarchy_of_containers_on_failure() {
- StartableComponent parentComponent = new StartableComponent();
- final StartableComponent childComponent1 = new StartableComponent();
- final UnstartableComponent childComponent2 = new UnstartableComponent();
- ComponentContainer parentContainer = new ComponentContainer() {
- @Override
- public void doAfterStart() {
- ComponentContainer childContainer = new ComponentContainer(this);
- childContainer.add(childComponent1);
- childContainer.add(childComponent2);
- childContainer.execute();
- }
- };
- parentContainer.add(parentComponent);
- try {
- parentContainer.execute();
- fail();
- } catch (Exception e) {
- assertThat(parentComponent.started).isTrue();
- assertThat(parentComponent.stopped).isTrue();
- assertThat(childComponent1.started).isTrue();
- assertThat(childComponent1.stopped).isTrue();
- }
- }
-
- @Test
- public void testChild() {
- ComponentContainer parent = new ComponentContainer();
- parent.startComponents();
-
- ComponentContainer child = parent.createChild();
- child.addSingleton(StartableComponent.class);
- child.startComponents();
-
- assertThat(child.getParent()).isSameAs(parent);
- assertThat(parent.getChild()).isSameAs(child);
- assertThat(child.getComponentByType(ComponentContainer.class)).isSameAs(child);
- assertThat(parent.getComponentByType(ComponentContainer.class)).isSameAs(parent);
- assertThat(child.getComponentByType(StartableComponent.class)).isNotNull();
- assertThat(parent.getComponentByType(StartableComponent.class)).isNull();
-
- parent.stopComponents();
- }
-
- @Test
- public void testRemoveChild() {
- ComponentContainer parent = new ComponentContainer();
- parent.startComponents();
-
- ComponentContainer child = parent.createChild();
- assertThat(parent.getChild()).isSameAs(child);
-
- parent.removeChild();
- assertThat(parent.getChild()).isNull();
- }
-
- @Test
- public void shouldForwardStartAndStopToDescendants() {
- ComponentContainer grandParent = new ComponentContainer();
- ComponentContainer parent = grandParent.createChild();
- ComponentContainer child = parent.createChild();
- child.addSingleton(StartableComponent.class);
-
- grandParent.startComponents();
-
- StartableComponent component = child.getComponentByType(StartableComponent.class);
- assertTrue(component.started);
-
- parent.stopComponents();
- assertTrue(component.stopped);
- }
-
- @Test
- public void shouldDeclareComponentProperties() {
- ComponentContainer container = new ComponentContainer();
- container.addSingleton(ComponentWithProperty.class);
-
- PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
- assertThat(propertyDefinitions.get("foo")).isNotNull();
- assertThat(propertyDefinitions.get("foo").defaultValue()).isEqualTo("bar");
- }
-
- @Test
- public void shouldDeclareExtensionWithoutAddingIt() {
- ComponentContainer container = new ComponentContainer();
- PluginMetadata plugin = mock(PluginMetadata.class);
- container.declareExtension(plugin, ComponentWithProperty.class);
-
- PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
- assertThat(propertyDefinitions.get("foo")).isNotNull();
- assertThat(container.getComponentByType(ComponentWithProperty.class)).isNull();
- }
-
- @Test
- public void shouldDeclareExtensionWhenAdding() {
- ComponentContainer container = new ComponentContainer();
- PluginMetadata plugin = mock(PluginMetadata.class);
- container.addExtension(plugin, ComponentWithProperty.class);
-
- PropertyDefinitions propertyDefinitions = container.getComponentByType(PropertyDefinitions.class);
- assertThat(propertyDefinitions.get("foo")).isNotNull();
- assertThat(container.getComponentByType(ComponentWithProperty.class)).isNotNull();
- assertThat(container.getComponentByKey(ComponentWithProperty.class)).isNotNull();
- }
-
- @Test
- public void test_add_class() {
- ComponentContainer container = new ComponentContainer();
- container.add(ComponentWithProperty.class, SimpleComponent.class);
- assertThat(container.getComponentByType(ComponentWithProperty.class)).isNotNull();
- assertThat(container.getComponentByType(SimpleComponent.class)).isNotNull();
- }
-
- @Test
- public void test_add_collection() {
- ComponentContainer container = new ComponentContainer();
- container.add(Arrays.asList(ComponentWithProperty.class, SimpleComponent.class));
- assertThat(container.getComponentByType(ComponentWithProperty.class)).isNotNull();
- assertThat(container.getComponentByType(SimpleComponent.class)).isNotNull();
- }
-
- @Test
- public void test_add_adapter() {
- ComponentContainer container = new ComponentContainer();
- container.add(new SimpleComponentProvider());
- assertThat(container.getComponentByType(SimpleComponent.class)).isNotNull();
- }
-
- @Test
- public void should_sanitize_pico_exception_on_start_failure() {
- ComponentContainer container = new ComponentContainer();
- container.add(UnstartableComponent.class);
-
- // do not expect a PicoException
- thrown.expect(IllegalStateException.class);
- container.startComponents();
- }
-
- @Test
- public void display_plugin_name_when_failing_to_add_extension() {
- ComponentContainer container = new ComponentContainer();
- PluginMetadata plugin = mock(PluginMetadata.class);
-
- container.startComponents();
-
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Unable to register extension org.sonar.api.platform.ComponentContainerTest$UnstartableComponent");
-
- container.addExtension(plugin, UnstartableComponent.class);
-
- }
-
- @Test
- public void test_start_failure() {
- ComponentContainer container = new ComponentContainer();
- StartableComponent startable = new StartableComponent();
- container.add(startable, UnstartableComponent.class);
-
- try {
- container.execute();
- fail();
- } catch (Exception e) {
- assertThat(startable.started).isTrue();
-
- // container stops the components that have already been started
- assertThat(startable.stopped).isTrue();
- }
- }
-
- @Test
- public void test_stop_failure() {
- ComponentContainer container = new ComponentContainer();
- StartableComponent startable = new StartableComponent();
- container.add(startable, UnstoppableComponent.class);
-
- try {
- container.execute();
- fail();
- } catch (Exception e) {
- assertThat(startable.started).isTrue();
-
- // container should stop the components that have already been started
- // ... but that's not the case
- }
- }
-
- @Test
- public void stop_exception_should_not_hide_start_exception() {
- ComponentContainer container = new ComponentContainer();
- container.add(UnstartableComponent.class, UnstoppableComponent.class);
-
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Fail to start");
- container.execute();
- }
-
- @Test
- public void should_execute_components() {
- ComponentContainer container = new ComponentContainer();
- StartableComponent component = new StartableComponent();
- container.add(component);
-
- container.execute();
-
- assertThat(component.started).isTrue();
- assertThat(component.stopped).isTrue();
- }
-
- /**
- * Method close() must be called even if the methods start() or stop()
- * are not defined.
- */
- @Test
- public void should_close_components_without_lifecycle() {
- ComponentContainer container = new ComponentContainer();
- CloseableComponent component = new CloseableComponent();
- container.add(component);
-
- container.execute();
-
- assertThat(component.isClosed).isTrue();
- }
-
- /**
- * Method close() must be executed after stop()
- */
- @Test
- public void should_close_components_with_lifecycle() {
- ComponentContainer container = new ComponentContainer();
- StartableCloseableComponent component = new StartableCloseableComponent();
- container.add(component);
-
- container.execute();
-
- assertThat(component.isStopped).isTrue();
- assertThat(component.isClosed).isTrue();
- assertThat(component.isClosedAfterStop).isTrue();
- }
-
- public static class StartableComponent {
- public boolean started = false, stopped = false;
-
- public void start() {
- started = true;
- }
-
- public void stop() {
- stopped = true;
- }
- }
-
- public static class UnstartableComponent {
- public void start() {
- throw new IllegalStateException("Fail to start");
- }
-
- public void stop() {
-
- }
- }
-
- public static class UnstoppableComponent {
- public void start() {
- }
-
- public void stop() {
- throw new IllegalStateException("Fail to stop");
- }
- }
-
- @Property(key = "foo", defaultValue = "bar", name = "Foo")
- public static class ComponentWithProperty {
-
- }
-
- public static class SimpleComponent {
-
- }
-
- public static class SimpleComponentProvider extends ProviderAdapter {
- public SimpleComponent provide() {
- return new SimpleComponent();
- }
- }
-
- public static class CloseableComponent implements AutoCloseable {
- public boolean isClosed = false;
-
- @Override
- public void close() throws Exception {
- isClosed = true;
- }
- }
-
- public static class StartableCloseableComponent implements AutoCloseable {
- public boolean isClosed = false, isStopped = false, isClosedAfterStop = false;
-
- public void stop() {
- isStopped = true;
- }
-
- @Override
- public void close() throws Exception {
- isClosed = true;
- isClosedAfterStop = isStopped;
- }
- }
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/platform/ComponentKeysTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/platform/ComponentKeysTest.java
deleted file mode 100644
index f2b36a677fe..00000000000
--- a/sonar-plugin-api/src/test/java/org/sonar/api/platform/ComponentKeysTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.platform;
-
-import org.junit.Test;
-import org.sonar.api.utils.log.Logger;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.*;
-
-public class ComponentKeysTest {
-
- ComponentKeys keys = new ComponentKeys();
-
- @Test
- public void generate_key_of_class() {
- assertThat(keys.of(FakeComponent.class)).isEqualTo(FakeComponent.class);
- }
-
- @Test
- public void generate_key_of_object() {
- assertThat(keys.of(new FakeComponent())).isEqualTo("org.sonar.api.platform.ComponentKeysTest.FakeComponent-fake");
- }
-
- @Test
- public void should_log_warning_if_toString_is_not_overridden() {
- Logger log = mock(Logger.class);
- keys.of(new Object(), log);
- verifyZeroInteractions(log);
-
- // only on non-first runs, to avoid false-positives on singletons
- keys.of(new Object(), log);
- verify(log).warn(startsWith("Bad component key"));
- }
-
- @Test
- public void should_generate_unique_key_when_toString_is_not_overridden() {
- Object key = keys.of(new WrongToStringImpl());
- assertThat(key).isNotEqualTo(WrongToStringImpl.KEY);
-
- Object key2 = keys.of(new WrongToStringImpl());
- assertThat(key2).isNotEqualTo(key);
- }
-
- static class FakeComponent {
- @Override
- public String toString() {
- return "fake";
- }
- }
-
- static class WrongToStringImpl {
- static final String KEY = "my.Component@123a";
-
- @Override
- public String toString() {
- return KEY;
- }
- }
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/platform/PicoUtilsTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/platform/PicoUtilsTest.java
deleted file mode 100644
index d5b74341b8b..00000000000
--- a/sonar-plugin-api/src/test/java/org/sonar/api/platform/PicoUtilsTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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.api.platform;
-
-import org.junit.Test;
-import org.picocontainer.Characteristics;
-import org.picocontainer.MutablePicoContainer;
-import org.picocontainer.PicoLifecycleException;
-
-import java.io.IOException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-
-
-public class PicoUtilsTest {
- @Test
- public void shouldSanitizePicoLifecycleException() {
- Throwable th = PicoUtils.sanitize(newPicoLifecycleException(false));
-
- assertThat(th).isInstanceOf(IllegalStateException.class);
- assertThat(th.getMessage()).isEqualTo("A good reason to fail");
- }
-
- @Test
- public void shouldSanitizePicoLifecycleException_no_wrapper_message() {
- Throwable th = PicoUtils.sanitize(new PicoLifecycleException(null, null, new IllegalStateException("msg")));
-
- assertThat(th).isInstanceOf(IllegalStateException.class);
- assertThat(th.getMessage()).isEqualTo("msg");
- }
-
- @Test
- public void shouldNotSanitizeOtherExceptions() {
- Throwable th = PicoUtils.sanitize(new IllegalArgumentException("foo"));
-
- assertThat(th).isInstanceOf(IllegalArgumentException.class);
- assertThat(th.getMessage()).isEqualTo("foo");
- }
-
- @Test
- public void shouldPropagateInitialUncheckedException() {
- try {
- PicoUtils.propagate(newPicoLifecycleException(false));
- fail();
- } catch (RuntimeException e) {
- assertThat(e).isInstanceOf(IllegalStateException.class);
- }
- }
-
- @Test
- public void shouldThrowUncheckedExceptionWhenPropagatingCheckedException() {
- try {
- PicoUtils.propagate(newPicoLifecycleException(true));
- fail();
- } catch (RuntimeException e) {
- assertThat(e.getCause()).isInstanceOf(IOException.class);
- assertThat(e.getCause().getMessage()).isEqualTo("Checked");
- }
- }
-
- private PicoLifecycleException newPicoLifecycleException(boolean initialCheckedException) {
- MutablePicoContainer container = ComponentContainer.createPicoContainer().as(Characteristics.CACHE);
- if (initialCheckedException) {
- container.addComponent(CheckedFailureComponent.class);
- } else {
- container.addComponent(UncheckedFailureComponent.class);
- }
- try {
- container.start();
- return null;
-
- } catch (PicoLifecycleException e) {
- return e;
- }
- }
-
- public static class UncheckedFailureComponent {
- public void start() {
- throw new IllegalStateException("A good reason to fail");
- }
- }
-
- public static class CheckedFailureComponent {
- public void start() throws IOException {
- throw new IOException("Checked");
- }
- }
-}