diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-04-24 09:15:05 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-05-11 10:21:55 +0200 |
commit | 14a5c982e5f1b28354a853073bd3e225b3914abe (patch) | |
tree | e298a2948f49628880f8d5290451adc14a920613 /sonar-plugin-api | |
parent | cba928d505985972e13c8e895b490a52702af925 (diff) | |
download | sonarqube-14a5c982e5f1b28354a853073bd3e225b3914abe.tar.gz sonarqube-14a5c982e5f1b28354a853073bd3e225b3914abe.zip |
SONAR-6370 isolate plugin classloader from core
Diffstat (limited to 'sonar-plugin-api')
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"); - } - } -} |