From: simonbrandhof Date: Thu, 11 Aug 2011 21:48:48 +0000 (+0200) Subject: SONAR-2692 API: allow plugins to auto-disable on server startup X-Git-Tag: 2.11^2~168 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=9cbf7d1d02aaf60f6e36ff259305d4474aa68230;p=sonarqube.git SONAR-2692 API: allow plugins to auto-disable on server startup --- diff --git a/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java b/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java index 56cb45aa239..ab0f9e6faa8 100644 --- a/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java +++ b/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java @@ -28,7 +28,7 @@ import org.sonar.api.platform.PluginMetadata; import java.io.File; import java.util.List; -public final class DefaultPluginMetadata implements PluginMetadata, Comparable { +public class DefaultPluginMetadata implements PluginMetadata, Comparable { private File file; private List deployedFiles = Lists.newArrayList(); private List deprecatedExtensions = Lists.newArrayList(); 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 index 2eb1ceb7de9..f2a544e3db0 100644 --- 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 @@ -22,11 +22,10 @@ package org.sonar.api.platform; import org.sonar.api.BatchComponent; import org.sonar.api.Plugin; import org.sonar.api.Property; -import org.sonar.api.ServerComponent; import java.util.Collection; -public interface PluginRepository extends BatchComponent, ServerComponent { +public interface PluginRepository extends BatchComponent { Collection getPlugins(); Plugin getPlugin(String key); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/ServerPluginRepository.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/ServerPluginRepository.java new file mode 100644 index 00000000000..fdab45aefb6 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/platform/ServerPluginRepository.java @@ -0,0 +1,43 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * 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.api.platform; + +import org.sonar.api.ServerComponent; + +/** + * @since 2.11 + */ +public interface ServerPluginRepository extends PluginRepository, ServerComponent { + + /** + * Disabled plugins are not loaded by batch, but they are still installed : + *
    + *
  • Plugin properties are available in General Settings
  • + *
  • Plugin is marked as installed in Update Center
  • + *
+ */ + void disable(String pluginKey); + + /** + * @param plugingKey can not be null + */ + boolean isDisabled(String plugingKey); + +} diff --git a/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java b/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java index aef353f6587..919217b72e0 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java @@ -155,7 +155,7 @@ public class DefaultServerFileSystem implements ServerFileSystem { return new File(getHomeDir(), "extensions/rules"); } - public File getPluginsIndex() { + public File getPluginIndex() { return new File(getDeployDir(), "plugins/index.txt"); } diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 6da88e0004a..a03fbdc1828 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -137,7 +137,7 @@ public final class Platform { private void startCoreComponents() { coreContainer = rootContainer.makeChildContainer(); coreContainer.as(Characteristics.CACHE).addComponent(PluginDeployer.class); - coreContainer.as(Characteristics.CACHE).addComponent(ServerPluginRepository.class); + coreContainer.as(Characteristics.CACHE).addComponent(DefaultServerPluginRepository.class); coreContainer.as(Characteristics.CACHE).addComponent(DefaultServerFileSystem.class); coreContainer.as(Characteristics.CACHE).addComponent(ThreadLocalDatabaseSessionFactory.class); coreContainer.as(Characteristics.CACHE).addComponent(HttpDownloader.class); @@ -158,7 +158,7 @@ public final class Platform { private void startServiceComponents() { servicesContainer = coreContainer.makeChildContainer(); - ServerPluginRepository pluginRepository = servicesContainer.getComponent(ServerPluginRepository.class); + DefaultServerPluginRepository pluginRepository = servicesContainer.getComponent(DefaultServerPluginRepository.class); pluginRepository.registerExtensions(servicesContainer); servicesContainer.as(Characteristics.CACHE).addComponent(ServerImpl.class); @@ -216,6 +216,7 @@ public final class Platform { startupContainer.as(Characteristics.CACHE).addComponent(ServerMetadataPersister.class); startupContainer.as(Characteristics.CACHE).addComponent(RegisterQualityModels.class); startupContainer.as(Characteristics.CACHE).addComponent(DeleteDeprecatedMeasures.class); + startupContainer.as(Characteristics.CACHE).addComponent(GeneratePluginIndex.class); startupContainer.start(); startupContainer.getComponent(ServerLifecycleNotifier.class).notifyStart(); diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/DefaultServerPluginRepository.java b/sonar-server/src/main/java/org/sonar/server/plugins/DefaultServerPluginRepository.java new file mode 100644 index 00000000000..4776c65eeee --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/plugins/DefaultServerPluginRepository.java @@ -0,0 +1,165 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * 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.server.plugins; + +import com.google.common.collect.Sets; +import org.picocontainer.Characteristics; +import org.picocontainer.MutablePicoContainer; +import org.slf4j.LoggerFactory; +import org.sonar.api.*; +import org.sonar.api.platform.PluginMetadata; +import org.sonar.api.platform.ServerPluginRepository; +import org.sonar.core.plugins.PluginClassloaders; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @since 2.2 + */ +public class DefaultServerPluginRepository implements ServerPluginRepository { + + private PluginClassloaders classloaders; + private PluginDeployer deployer; + private Map pluginsByKey; + private Set disabledPlugins = Sets.newHashSet(); + + public DefaultServerPluginRepository(PluginDeployer deployer) { + this.classloaders = new PluginClassloaders(getClass().getClassLoader()); + this.deployer = deployer; + } + + public void start() { + pluginsByKey = classloaders.init(deployer.getMetadata()); + } + + public void stop() { + if (classloaders != null) { + classloaders.clean(); + classloaders = null; + } + } + + public void disable(String pluginKey) { + disabledPlugins.add(pluginKey); + for (PluginMetadata metadata : getMetadata()) { + if (pluginKey.equals(metadata.getBasePlugin())) { + disable(metadata.getKey()); + } + } + } + + public boolean isDisabled(String pluginKey) { + return disabledPlugins.contains(pluginKey); + } + + public Collection getPlugins() { + return pluginsByKey.values(); + } + + public Plugin getPlugin(String key) { + return pluginsByKey.get(key); + } + + public ClassLoader getClassloader(String pluginKey) { + return classloaders.get(pluginKey); + } + + public Class getClass(String pluginKey, String classname) { + Class clazz = null; + ClassLoader classloader = getClassloader(pluginKey); + if (classloader != null) { + try { + clazz = classloader.loadClass(classname); + + } catch (ClassNotFoundException e) { + LoggerFactory.getLogger(getClass()).warn("Class not found in plugin " + pluginKey + ": " + classname, e); + } + } + return clazz; + } + + + public Property[] getProperties(Plugin plugin) { + if (plugin != null) { + Class classInstance = plugin.getClass(); + if (classInstance.isAnnotationPresent(Properties.class)) { + return classInstance.getAnnotation(Properties.class).value(); + } + } + return new Property[0]; + } + + public Collection getMetadata() { + return deployer.getMetadata(); + } + + public PluginMetadata getMetadata(String pluginKey) { + return deployer.getMetadata(pluginKey); + } + + public void registerExtensions(MutablePicoContainer container) { + registerExtensions(container, getPlugins()); + } + + void registerExtensions(MutablePicoContainer container, Collection plugins) { + for (Plugin plugin : plugins) { + container.as(Characteristics.CACHE).addComponent(plugin); + for (Object extension : plugin.getExtensions()) { + installExtension(container, extension); + } + } + installExtensionProviders(container); + } + + void installExtensionProviders(MutablePicoContainer container) { + List providers = container.getComponents(ExtensionProvider.class); + for (ExtensionProvider provider : providers) { + Object obj = provider.provide(); + if (obj instanceof Iterable) { + for (Object extension : (Iterable) obj) { + installExtension(container, extension); + } + } else { + installExtension(container, obj); + } + } + } + + void installExtension(MutablePicoContainer container, Object extension) { + if (isType(extension, ServerExtension.class)) { + container.as(Characteristics.CACHE).addComponent(getExtensionKey(extension), extension); + } + } + + static boolean isType(Object extension, Class extensionClass) { + Class clazz = (extension instanceof Class ? (Class) extension : extension.getClass()); + return extensionClass.isAssignableFrom(clazz); + } + + static Object getExtensionKey(Object component) { + if (component instanceof Class) { + return component; + } + return component.getClass().getCanonicalName() + "-" + component.toString(); + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java b/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java index a5c9281dbd3..3f957be9170 100644 --- a/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java +++ b/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java @@ -22,8 +22,6 @@ package org.sonar.server.plugins; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.CharUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,12 +32,10 @@ import org.sonar.api.utils.SonarException; import org.sonar.api.utils.TimeProfiler; import org.sonar.core.plugins.DefaultPluginMetadata; import org.sonar.core.plugins.PluginFileExtractor; -import org.sonar.core.plugins.RemotePlugin; import org.sonar.server.platform.DefaultServerFileSystem; import org.sonar.server.platform.ServerStartException; import java.io.File; -import java.io.FileWriter; import java.io.IOException; import java.util.Collection; import java.util.List; @@ -73,7 +69,6 @@ public class PluginDeployer implements ServerComponent { deployPlugins(); - generateIndexFile(); profiler.stop(); } @@ -148,24 +143,6 @@ public class PluginDeployer implements ServerComponent { } } - - private void generateIndexFile() throws IOException { - File indexFile = fileSystem.getPluginsIndex(); - FileUtils.forceMkdir(indexFile.getParentFile()); - FileWriter writer = new FileWriter(indexFile, false); - try { - for (PluginMetadata metadata : pluginByKeys.values()) { - writer.append(RemotePlugin.create((DefaultPluginMetadata)metadata).marshal()); - writer.append(CharUtils.LF); - } - writer.flush(); - - } finally { - IOUtils.closeQuietly(writer); - } - } - - public void uninstall(String pluginKey) { PluginMetadata metadata = pluginByKeys.get(pluginKey); if (metadata != null && !metadata.isCore()) { diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java b/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java deleted file mode 100644 index b937d6d30c0..00000000000 --- a/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * 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.server.plugins; - -import org.picocontainer.Characteristics; -import org.picocontainer.MutablePicoContainer; -import org.slf4j.LoggerFactory; -import org.sonar.api.*; -import org.sonar.api.platform.PluginMetadata; -import org.sonar.api.platform.PluginRepository; -import org.sonar.core.plugins.PluginClassloaders; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -/** - * @since 2.2 - */ -public class ServerPluginRepository implements PluginRepository { - - private PluginClassloaders classloaders; - private PluginDeployer deployer; - private Map pluginsByKey; - - public ServerPluginRepository(PluginDeployer deployer) { - this.classloaders = new PluginClassloaders(getClass().getClassLoader()); - this.deployer = deployer; - } - - public void start() { - pluginsByKey = classloaders.init(deployer.getMetadata()); - } - - public void stop() { - if (classloaders != null) { - classloaders.clean(); - classloaders = null; - } - } - - public Collection getPlugins() { - return pluginsByKey.values(); - } - - public Plugin getPlugin(String key) { - return pluginsByKey.get(key); - } - - public ClassLoader getClassloader(String pluginKey) { - return classloaders.get(pluginKey); - } - - public Class getClass(String pluginKey, String classname) { - Class clazz = null; - ClassLoader classloader = getClassloader(pluginKey); - if (classloader != null) { - try { - clazz = classloader.loadClass(classname); - - } catch (ClassNotFoundException e) { - LoggerFactory.getLogger(getClass()).warn("Class not found in plugin " + pluginKey + ": " + classname, e); - } - } - return clazz; - } - - - public Property[] getProperties(Plugin plugin) { - if (plugin != null) { - Class classInstance = plugin.getClass(); - if (classInstance.isAnnotationPresent(Properties.class)) { - return classInstance.getAnnotation(Properties.class).value(); - } - } - return new Property[0]; - } - - public Collection getMetadata() { - return deployer.getMetadata(); - } - - public PluginMetadata getMetadata(String pluginKey) { - return deployer.getMetadata(pluginKey); - } - - public void registerExtensions(MutablePicoContainer container) { - registerExtensions(container, getPlugins()); - } - - void registerExtensions(MutablePicoContainer container, Collection plugins) { - for (Plugin plugin : plugins) { - container.as(Characteristics.CACHE).addComponent(plugin); - for (Object extension : plugin.getExtensions()) { - installExtension(container, extension); - } - } - installExtensionProviders(container); - } - - void installExtensionProviders(MutablePicoContainer container) { - List providers = container.getComponents(ExtensionProvider.class); - for (ExtensionProvider provider : providers) { - Object obj = provider.provide(); - if (obj instanceof Iterable) { - for (Object extension : (Iterable) obj) { - installExtension(container, extension); - } - } else { - installExtension(container, obj); - } - } - } - - void installExtension(MutablePicoContainer container, Object extension) { - if (isType(extension, ServerExtension.class)) { - container.as(Characteristics.CACHE).addComponent(getExtensionKey(extension), extension); - } - } - - static boolean isType(Object extension, Class extensionClass) { - Class clazz = (extension instanceof Class ? (Class) extension : extension.getClass()); - return extensionClass.isAssignableFrom(clazz); - } - - static Object getExtensionKey(Object component) { - if (component instanceof Class) { - return component; - } - return component.getClass().getCanonicalName() + "-" + component.toString(); - } -} diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java b/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java index 1ba14e3c38c..1dca1b380ea 100644 --- a/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java +++ b/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java @@ -44,7 +44,7 @@ public class StaticResourcesServlet extends HttpServlet { String pluginKey = getPluginKey(request); String resource = getResourcePath(request); - ServerPluginRepository pluginRepository = Platform.getInstance().getContainer().getComponent(ServerPluginRepository.class); + DefaultServerPluginRepository pluginRepository = Platform.getInstance().getContainer().getComponent(DefaultServerPluginRepository.class); ClassLoader classLoader = pluginRepository.getClassloader(pluginKey); if (classLoader == null) { LOG.error("Plugin not found: " + pluginKey); diff --git a/sonar-server/src/main/java/org/sonar/server/startup/GeneratePluginIndex.java b/sonar-server/src/main/java/org/sonar/server/startup/GeneratePluginIndex.java new file mode 100644 index 00000000000..41317a5f5d5 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/startup/GeneratePluginIndex.java @@ -0,0 +1,68 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * 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.server.startup; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.CharUtils; +import org.sonar.api.platform.PluginMetadata; +import org.sonar.core.plugins.DefaultPluginMetadata; +import org.sonar.core.plugins.RemotePlugin; +import org.sonar.server.platform.DefaultServerFileSystem; +import org.sonar.server.plugins.DefaultServerPluginRepository; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +/** + * @since 2.11 + */ +public final class GeneratePluginIndex { + + private DefaultServerFileSystem fileSystem; + private DefaultServerPluginRepository repository; + + public GeneratePluginIndex(DefaultServerFileSystem fileSystem, DefaultServerPluginRepository repository) { + this.fileSystem = fileSystem; + this.repository = repository; + } + + public void start() throws IOException { + writeIndex(fileSystem.getPluginIndex()); + } + + void writeIndex(File indexFile) throws IOException { + FileUtils.forceMkdir(indexFile.getParentFile()); + FileWriter writer = new FileWriter(indexFile, false); + try { + for (PluginMetadata metadata : repository.getMetadata()) { + if (!repository.isDisabled(metadata.getKey())) { + writer.append(RemotePlugin.create((DefaultPluginMetadata) metadata).marshal()); + writer.append(CharUtils.LF); + } + } + writer.flush(); + + } finally { + IOUtils.closeQuietly(writer); + } + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java index e72305ebacd..1efadaabc4a 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java @@ -296,7 +296,7 @@ public final class JRubyFacade { public Object getComponentByClassname(String pluginKey, String className) { Object component = null; PicoContainer container = getContainer(); - Class componentClass = container.getComponent(ServerPluginRepository.class).getClass(pluginKey, className); + Class componentClass = container.getComponent(DefaultServerPluginRepository.class).getClass(pluginKey, className); if (componentClass != null) { component = container.getComponent(componentClass); } diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/DefaultServerPluginRepositoryTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/DefaultServerPluginRepositoryTest.java new file mode 100644 index 00000000000..7624e422b07 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/plugins/DefaultServerPluginRepositoryTest.java @@ -0,0 +1,178 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * 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.server.plugins; + +import org.apache.commons.io.FileUtils; +import org.hamcrest.core.Is; +import org.junit.After; +import org.junit.Test; +import org.picocontainer.containers.TransientPicoContainer; +import org.sonar.api.*; +import org.sonar.api.platform.PluginMetadata; +import org.sonar.core.plugins.DefaultPluginMetadata; + +import java.io.File; +import java.util.Arrays; +import java.util.List; + +import static junit.framework.Assert.assertFalse; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class DefaultServerPluginRepositoryTest { + + private DefaultServerPluginRepository repository; + + @After + public void stop() { + if (repository != null) { + repository.stop(); + } + } + + @Test + public void testStart() { + PluginDeployer deployer = mock(PluginDeployer.class); + File pluginFile = FileUtils.toFile(getClass().getResource("/org/sonar/server/plugins/DefaultServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar")); + PluginMetadata plugin = DefaultPluginMetadata.create(pluginFile) + .setKey("artifactsize") + .setMainClass("org.sonar.plugins.artifactsize.ArtifactSizePlugin") + .addDeployedFile(pluginFile); + when(deployer.getMetadata()).thenReturn(Arrays.asList(plugin)); + + repository = new DefaultServerPluginRepository(deployer); + repository.start(); + + assertThat(repository.getPlugins().size(), Is.is(1)); + assertThat(repository.getPlugin("artifactsize"), not(nullValue())); + assertThat(repository.getClassloader("artifactsize"), not(nullValue())); + assertThat(repository.getClass("artifactsize", "org.sonar.plugins.artifactsize.ArtifactSizeMetrics"), not(nullValue())); + assertThat(repository.getClass("artifactsize", "org.Unknown"), nullValue()); + assertThat(repository.getClass("other", "org.sonar.plugins.artifactsize.ArtifactSizeMetrics"), nullValue()); + } + + @Test + public void shouldRegisterServerExtensions() { + DefaultServerPluginRepository repository = new DefaultServerPluginRepository(mock(PluginDeployer.class)); + + TransientPicoContainer container = new TransientPicoContainer(); + repository.registerExtensions(container, Arrays.asList(new FakePlugin(Arrays.asList(FakeBatchExtension.class, FakeServerExtension.class)))); + + assertThat(container.getComponents(Extension.class).size(), is(1)); + assertThat(container.getComponents(FakeServerExtension.class).size(), is(1)); + assertThat(container.getComponents(FakeBatchExtension.class).size(), is(0)); + } + + @Test + public void shouldInvokeServerExtensionProviderss() { + DefaultServerPluginRepository repository = new DefaultServerPluginRepository(mock(PluginDeployer.class)); + + TransientPicoContainer container = new TransientPicoContainer(); + repository.registerExtensions(container, Arrays.asList(new FakePlugin(Arrays.asList(FakeExtensionProvider.class)))); + + assertThat(container.getComponents(Extension.class).size(), is(2));// provider + FakeServerExtension + assertThat(container.getComponents(FakeServerExtension.class).size(), is(1)); + assertThat(container.getComponents(FakeBatchExtension.class).size(), is(0)); + } + + @Test + public void shouldDisablePlugin() { + DefaultServerPluginRepository repository = new DefaultServerPluginRepository(mock(PluginDeployer.class)); + repository.disable("checkstyle"); + + assertTrue(repository.isDisabled("checkstyle")); + assertFalse(repository.isDisabled("sqale")); + } + + @Test + public void shouldDisableDependentPlugins() { + PluginDeployer deployer = mock(PluginDeployer.class); + List metadata = Arrays.asList( + newMetadata("checkstyle", null), + newMetadata("checkstyle-extensions", "checkstyle"), + newMetadata("sqale", null) + ); + when(deployer.getMetadata()).thenReturn(metadata); + DefaultServerPluginRepository repository = new DefaultServerPluginRepository(deployer); + + repository.disable("checkstyle"); + + assertTrue(repository.isDisabled("checkstyle")); + assertTrue(repository.isDisabled("checkstyle-extensions")); + assertFalse(repository.isDisabled("sqale")); + } + + @Test + public void shouldNotDisableBasePlugin() { + PluginDeployer deployer = mock(PluginDeployer.class); + List metadata = Arrays.asList( + newMetadata("checkstyle", null), + newMetadata("checkstyle-extensions", "checkstyle"), + newMetadata("sqale", null) + ); + when(deployer.getMetadata()).thenReturn(metadata); + DefaultServerPluginRepository repository = new DefaultServerPluginRepository(deployer); + + repository.disable("checkstyle-extensions"); + + assertFalse(repository.isDisabled("checkstyle")); + assertTrue(repository.isDisabled("checkstyle-extensions")); + } + + private PluginMetadata newMetadata(String pluginKey, String basePluginKey) { + PluginMetadata plugin = mock(PluginMetadata.class); + when(plugin.getKey()).thenReturn(pluginKey); + when(plugin.getBasePlugin()).thenReturn(basePluginKey); + return plugin; + } + + public static class FakePlugin extends SonarPlugin { + private List extensions; + + public FakePlugin(List extensions) { + this.extensions = extensions; + } + + public List getExtensions() { + return extensions; + } + } + + public static class FakeBatchExtension implements BatchExtension { + + } + + public static class FakeServerExtension implements ServerExtension { + + } + + public static class FakeExtensionProvider extends ExtensionProvider implements ServerExtension { + + @Override + public Object provide() { + return Arrays.asList(FakeBatchExtension.class, FakeServerExtension.class); + } + } +} diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java deleted file mode 100644 index dcc85e5b519..00000000000 --- a/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2011 SonarSource - * 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.server.plugins; - -import org.apache.commons.io.FileUtils; -import org.hamcrest.core.Is; -import org.junit.After; -import org.junit.Test; -import org.picocontainer.containers.TransientPicoContainer; -import org.sonar.api.*; -import org.sonar.api.platform.PluginMetadata; -import org.sonar.core.plugins.DefaultPluginMetadata; - -import java.io.File; -import java.util.Arrays; -import java.util.List; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.core.IsNot.not; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ServerPluginRepositoryTest { - - private ServerPluginRepository repository; - - @After - public void stop() { - if (repository != null) { - repository.stop(); - } - } - - @Test - public void testStart() { - PluginDeployer deployer = mock(PluginDeployer.class); - File pluginFile = FileUtils.toFile(getClass().getResource("/org/sonar/server/plugins/ServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar")); - PluginMetadata plugin = DefaultPluginMetadata.create(pluginFile) - .setKey("artifactsize") - .setMainClass("org.sonar.plugins.artifactsize.ArtifactSizePlugin") - .addDeployedFile(pluginFile); - when(deployer.getMetadata()).thenReturn(Arrays.asList(plugin)); - - repository = new ServerPluginRepository(deployer); - repository.start(); - - assertThat(repository.getPlugins().size(), Is.is(1)); - assertThat(repository.getPlugin("artifactsize"), not(nullValue())); - assertThat(repository.getClassloader("artifactsize"), not(nullValue())); - assertThat(repository.getClass("artifactsize", "org.sonar.plugins.artifactsize.ArtifactSizeMetrics"), not(nullValue())); - assertThat(repository.getClass("artifactsize", "org.Unknown"), nullValue()); - assertThat(repository.getClass("other", "org.sonar.plugins.artifactsize.ArtifactSizeMetrics"), nullValue()); - } - - @Test - public void shouldRegisterServerExtensions() { - ServerPluginRepository repository = new ServerPluginRepository(mock(PluginDeployer.class)); - - TransientPicoContainer container = new TransientPicoContainer(); - repository.registerExtensions(container, Arrays.asList(new FakePlugin(Arrays.asList(FakeBatchExtension.class, FakeServerExtension.class)))); - - assertThat(container.getComponents(Extension.class).size(), is(1)); - assertThat(container.getComponents(FakeServerExtension.class).size(), is(1)); - assertThat(container.getComponents(FakeBatchExtension.class).size(), is(0)); - } - - @Test - public void shouldInvokeServerExtensionProviderss() { - ServerPluginRepository repository = new ServerPluginRepository(mock(PluginDeployer.class)); - - TransientPicoContainer container = new TransientPicoContainer(); - repository.registerExtensions(container, Arrays.asList(new FakePlugin(Arrays.asList(FakeExtensionProvider.class)))); - - assertThat(container.getComponents(Extension.class).size(), is(2));// provider + FakeServerExtension - assertThat(container.getComponents(FakeServerExtension.class).size(), is(1)); - assertThat(container.getComponents(FakeBatchExtension.class).size(), is(0)); - } - - public static class FakePlugin extends SonarPlugin { - private List extensions; - - public FakePlugin(List extensions) { - this.extensions = extensions; - } - - public List getExtensions() { - return extensions; - } - } - - public static class FakeBatchExtension implements BatchExtension { - - } - - public static class FakeServerExtension implements ServerExtension { - - } - - public static class FakeExtensionProvider extends ExtensionProvider implements ServerExtension { - - @Override - public Object provide() { - return Arrays.asList(FakeBatchExtension.class, FakeServerExtension.class); - } - } -} diff --git a/sonar-server/src/test/java/org/sonar/server/startup/GeneratePluginIndexTest.java b/sonar-server/src/test/java/org/sonar/server/startup/GeneratePluginIndexTest.java new file mode 100644 index 00000000000..38c26893317 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/startup/GeneratePluginIndexTest.java @@ -0,0 +1,89 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * 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.server.startup; + +import org.apache.commons.io.FileUtils; +import org.hamcrest.core.Is; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.platform.PluginMetadata; +import org.sonar.core.plugins.DefaultPluginMetadata; +import org.sonar.server.platform.DefaultServerFileSystem; +import org.sonar.server.plugins.DefaultServerPluginRepository; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertThat; +import static org.junit.matchers.JUnitMatchers.containsString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class GeneratePluginIndexTest { + + private DefaultServerFileSystem fileSystem; + private File index; + + @Before + public void createIndexFile() { + fileSystem = mock(DefaultServerFileSystem.class); + index = new File("target/test-tmp/GeneratePluginIndexTest/plugins.txt"); + when(fileSystem.getPluginIndex()).thenReturn(index); + } + + @Test + public void shouldWriteIndex() throws IOException { + DefaultServerPluginRepository repository = mock(DefaultServerPluginRepository.class); + PluginMetadata sqale = newMetadata("sqale"); + PluginMetadata checkstyle = newMetadata("checkstyle"); + when(repository.getMetadata()).thenReturn(Arrays.asList(sqale, checkstyle)); + + new GeneratePluginIndex(fileSystem, repository).start(); + + List lines = FileUtils.readLines(index); + assertThat(lines.size(), Is.is(2)); + assertThat(lines.get(0), containsString("sqale")); + assertThat(lines.get(1), containsString("checkstyle")); + } + + @Test + public void shouldSkipDisabledPlugin() throws IOException { + DefaultServerPluginRepository repository = mock(DefaultServerPluginRepository.class); + PluginMetadata sqale = newMetadata("sqale"); + PluginMetadata checkstyle = newMetadata("checkstyle"); + when(repository.getMetadata()).thenReturn(Arrays.asList(sqale, checkstyle)); + when(repository.isDisabled("checkstyle")).thenReturn(true); + + new GeneratePluginIndex(fileSystem, repository).start(); + + List lines = FileUtils.readLines(index); + assertThat(lines.size(), Is.is(1)); + assertThat(lines.get(0), containsString("sqale")); + } + + private PluginMetadata newMetadata(String pluginKey) { + PluginMetadata plugin = mock(DefaultPluginMetadata.class); + when(plugin.getKey()).thenReturn(pluginKey); + when(plugin.getFile()).thenReturn(new File(pluginKey + ".jar")); + return plugin; + } +} diff --git a/sonar-server/src/test/resources/org/sonar/server/plugins/DefaultServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar b/sonar-server/src/test/resources/org/sonar/server/plugins/DefaultServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar new file mode 100644 index 00000000000..19533234582 Binary files /dev/null and b/sonar-server/src/test/resources/org/sonar/server/plugins/DefaultServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar differ diff --git a/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar b/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar deleted file mode 100644 index 19533234582..00000000000 Binary files a/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar and /dev/null differ