]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2692 API: allow plugins to auto-disable on server startup
authorsimonbrandhof <simon.brandhof@gmail.com>
Thu, 11 Aug 2011 21:48:48 +0000 (23:48 +0200)
committersimonbrandhof <simon.brandhof@gmail.com>
Thu, 11 Aug 2011 21:48:48 +0000 (23:48 +0200)
16 files changed:
sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java
sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginRepository.java
sonar-plugin-api/src/main/java/org/sonar/api/platform/ServerPluginRepository.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java
sonar-server/src/main/java/org/sonar/server/platform/Platform.java
sonar-server/src/main/java/org/sonar/server/plugins/DefaultServerPluginRepository.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java
sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java [deleted file]
sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java
sonar-server/src/main/java/org/sonar/server/startup/GeneratePluginIndex.java [new file with mode: 0644]
sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
sonar-server/src/test/java/org/sonar/server/plugins/DefaultServerPluginRepositoryTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java [deleted file]
sonar-server/src/test/java/org/sonar/server/startup/GeneratePluginIndexTest.java [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/plugins/DefaultServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar [deleted file]

index 56cb45aa239929edaa4fc3fdc31f7c982bd9101c..ab0f9e6faa8bc18f36f97b702de20f49f142cd5d 100644 (file)
@@ -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<PluginMetadata> {
+public class DefaultPluginMetadata implements PluginMetadata, Comparable<PluginMetadata> {
   private File file;
   private List<File> deployedFiles = Lists.newArrayList();
   private List<File> deprecatedExtensions = Lists.newArrayList();
index 2eb1ceb7de9c83096628eebd0831e4f735f38f8d..f2a544e3db063708b231e2577a9f18149c0eb992 100644 (file)
@@ -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<Plugin> 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 (file)
index 0000000..fdab45a
--- /dev/null
@@ -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 :
+   * <ul>
+   *   <li>Plugin properties are available in General Settings</li>
+   *   <li>Plugin is marked as installed in Update Center</li>
+   * </ul>
+   */
+  void disable(String pluginKey);
+
+  /**
+   * @param plugingKey can not be null
+   */
+  boolean isDisabled(String plugingKey);
+
+}
index aef353f6587d0af905bbaf74832fbee1cb5b98c0..919217b72e0f969fd31b481c6ba245fd14705715 100644 (file)
@@ -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");
   }
 
index 6da88e0004a29e909d1752908df92f580d88a61d..a03fbdc1828cf31ad8fe164d3b1ce7a1565e034c 100644 (file)
@@ -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 (file)
index 0000000..4776c65
--- /dev/null
@@ -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<String, Plugin> pluginsByKey;
+  private Set<String> 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<Plugin> 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<? extends Plugin> classInstance = plugin.getClass();
+      if (classInstance.isAnnotationPresent(Properties.class)) {
+        return classInstance.getAnnotation(Properties.class).value();
+      }
+    }
+    return new Property[0];
+  }
+
+  public Collection<PluginMetadata> 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<Plugin> 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<ExtensionProvider> 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<? extends Extension> 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();
+  }
+}
index a5c9281dbd3cb53be9898557a50c5ffd6ceb60f5..3f957be91700564c5bd5888b8ee2ebe019f1a138 100644 (file)
@@ -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 (file)
index b937d6d..0000000
+++ /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<String, Plugin> 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<Plugin> 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<? extends Plugin> classInstance = plugin.getClass();
-      if (classInstance.isAnnotationPresent(Properties.class)) {
-        return classInstance.getAnnotation(Properties.class).value();
-      }
-    }
-    return new Property[0];
-  }
-
-  public Collection<PluginMetadata> 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<Plugin> 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<ExtensionProvider> 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<? extends Extension> 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();
-  }
-}
index 1ba14e3c38cba0568b0dee080c528de7e02b903c..1dca1b380eac0edf2f6a60a1f14d559e2f0e6c8a 100644 (file)
@@ -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 (file)
index 0000000..41317a5
--- /dev/null
@@ -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);
+    }
+  }
+}
index e72305ebacd874796fd53ead2d8346fb500d03ea..1efadaabc4a27fa0bc541795ef18edf063002424 100644 (file)
@@ -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 (file)
index 0000000..7624e42
--- /dev/null
@@ -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.<Plugin>asList(new FakePlugin(Arrays.<Class>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.<Plugin>asList(new FakePlugin(Arrays.<Class>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<PluginMetadata> 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<PluginMetadata> 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<Class> extensions;
+
+    public FakePlugin(List<Class> 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 (file)
index dcc85e5..0000000
+++ /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.<Plugin>asList(new FakePlugin(Arrays.<Class>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.<Plugin>asList(new FakePlugin(Arrays.<Class>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<Class> extensions;
-
-    public FakePlugin(List<Class> 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 (file)
index 0000000..38c2689
--- /dev/null
@@ -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<String> 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<String> 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 (file)
index 0000000..1953323
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 (file)
index 1953323..0000000
Binary files a/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar and /dev/null differ