From: Simon Brandhof
Date: Fri, 24 Apr 2015 07:15:05 +0000 (+0200)
Subject: SONAR-6370 isolate plugin classloader from core
X-Git-Tag: 5.2-RC1~2007
X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=14a5c982e5f1b28354a853073bd3e225b3914abe;p=sonarqube.git
SONAR-6370 isolate plugin classloader from core
---
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/charts/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/charts/package-info.java
index 080a6b643ec..6d9fc80d519 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/charts/package-info.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/charts/package-info.java
@@ -17,9 +17,6 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/**
- * Deprecated in 4.5.1. JFreechart charts are replaced by Javascript charts.
- */
@ParametersAreNonnullByDefault
package org.sonar.plugins.core.charts;
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/dashboards/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/dashboards/package-info.java
index 30550df1482..d901586ae25 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/dashboards/package-info.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/dashboards/package-info.java
@@ -17,9 +17,6 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/**
- * Deprecated in 4.5.1. JFreechart charts are replaced by Javascript charts.
- */
@ParametersAreNonnullByDefault
package org.sonar.plugins.core.dashboards;
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/notifications/alerts/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/notifications/alerts/package-info.java
index a2cb7d768c1..5e28de8ee2c 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/notifications/alerts/package-info.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/notifications/alerts/package-info.java
@@ -17,9 +17,6 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/**
- * Deprecated in 4.5.1. JFreechart charts are replaced by Javascript charts.
- */
@ParametersAreNonnullByDefault
package org.sonar.plugins.core.notifications.alerts;
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/package-info.java
index 03fd8c46350..df9ccea5073 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/package-info.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/package-info.java
@@ -17,9 +17,6 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/**
- * Deprecated in 4.5.1. JFreechart charts are replaced by Javascript charts.
- */
@ParametersAreNonnullByDefault
package org.sonar.plugins.core.security;
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/package-info.java
index 870522ec56f..8d487ae9500 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/package-info.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/package-info.java
@@ -17,9 +17,6 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-/**
- * Deprecated in 4.5.1. JFreechart charts are replaced by Javascript charts.
- */
@ParametersAreNonnullByDefault
package org.sonar.plugins.core.timemachine;
diff --git a/pom.xml b/pom.xml
index 2dee8a71b58..3d6388fb8b0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -595,6 +595,11 @@
sonar-channel
4.1
+
+ org.codehaus.sonar
+ sonar-classloader
+ 1.0
+
org.codehaus.sonar
sonar-markdown
@@ -707,11 +712,6 @@
-
- org.codehaus.plexus
- plexus-classworlds
- 2.5.1
-
com.tinkerpop.blueprints
blueprints-core
diff --git a/server/sonar-server/pom.xml b/server/sonar-server/pom.xml
index 78e7f995a1e..fd3ee697d4f 100644
--- a/server/sonar-server/pom.xml
+++ b/server/sonar-server/pom.xml
@@ -248,7 +248,19 @@
src/main/resources
true
+
+
+
+ src/test/resources
+ false
+
+
+ src/test/projects
+ false
+
+
+
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContainer.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContainer.java
index 95ad3ef370e..d95084053ae 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContainer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContainer.java
@@ -19,7 +19,7 @@
*/
package org.sonar.server.computation;
-import org.sonar.api.platform.ComponentContainer;
+import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.issue.db.UpdateConflictResolver;
import org.sonar.server.computation.issue.*;
import org.sonar.server.computation.measure.MetricCache;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrator.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrator.java
index b506fc5244a..7158b0d5e6d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrator.java
@@ -29,9 +29,9 @@ import org.sonar.api.platform.ServerUpgradeStatus;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.persistence.DdlUtils;
import org.sonar.server.db.DbClient;
-import org.sonar.server.plugins.ServerPluginRepository;
import com.google.common.annotations.VisibleForTesting;
+import org.sonar.server.plugins.ServerPluginRepository;
/**
* Restore schema by executing DDL scripts. Only H2 database is supported.
@@ -46,10 +46,10 @@ public class DatabaseMigrator implements ServerComponent, Startable {
private final ServerUpgradeStatus serverUpgradeStatus;
/**
- * ServerPluginRepository is used to ensure H2 schema creation is done only after copy of bundle plugins have been done
+ * ServerPluginInstaller is used to ensure H2 schema creation is done only after copy of bundle plugins have been done
*/
public DatabaseMigrator(DbClient dbClient, MigrationStep[] migrations, ServerUpgradeStatus serverUpgradeStatus,
- ServerPluginRepository serverPluginRepository) {
+ ServerPluginRepository unused) {
this.dbClient = dbClient;
this.migrations = migrations;
this.serverUpgradeStatus = serverUpgradeStatus;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/debt/DebtModelPluginRepository.java b/server/sonar-server/src/main/java/org/sonar/server/debt/DebtModelPluginRepository.java
index b0e1cb6bd20..da45c47bf68 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/debt/DebtModelPluginRepository.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/debt/DebtModelPluginRepository.java
@@ -25,9 +25,9 @@ import com.google.common.collect.Maps;
import org.apache.commons.io.Charsets;
import org.picocontainer.Startable;
import org.sonar.api.Plugin;
-import org.sonar.api.ServerExtension;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
+import org.sonar.api.ServerComponent;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
import java.io.InputStreamReader;
import java.io.Reader;
@@ -45,7 +45,7 @@ import static com.google.common.collect.Lists.newArrayList;
* they must be named "-model.xml".
*
*/
-public class DebtModelPluginRepository implements ServerExtension, Startable {
+public class DebtModelPluginRepository implements ServerComponent, Startable {
public static final String DEFAULT_MODEL = "technical-debt";
@@ -87,14 +87,12 @@ public class DebtModelPluginRepository implements ServerExtension, Startable {
contributingPluginKeyToClassLoader = Maps.newTreeMap();
// Add default model
contributingPluginKeyToClassLoader.put(DEFAULT_MODEL, getClass().getClassLoader());
- for (PluginMetadata metadata : pluginRepository.getMetadata()) {
- String pluginKey = metadata.getKey();
- Plugin plugin = pluginRepository.getPlugin(pluginKey);
- if (plugin != null) {
- ClassLoader classLoader = plugin.getClass().getClassLoader();
- if (classLoader.getResource(getXMLFilePath(pluginKey)) != null) {
- contributingPluginKeyToClassLoader.put(pluginKey, classLoader);
- }
+ for (PluginInfo pluginInfo : pluginRepository.getPluginInfos()) {
+ String pluginKey = pluginInfo.getKey();
+ Plugin plugin = pluginRepository.getPluginInstance(pluginKey);
+ ClassLoader classLoader = plugin.getClass().getClassLoader();
+ if (classLoader.getResource(getXMLFilePath(pluginKey)) != null) {
+ contributingPluginKeyToClassLoader.put(pluginKey, classLoader);
}
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java b/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java
index df520c3900a..5258e753057 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java
@@ -127,27 +127,16 @@ public class DefaultServerFileSystem implements ServerFileSystem, Startable {
return new File(getHomeDir(), "extensions/downloads");
}
- public File getTrashPluginsDir() {
- return new File(getHomeDir(), "extensions/trash");
- }
-
- public List getCorePlugins() {
- File corePluginsDir = new File(getHomeDir(), "lib/core-plugins");
- return getFiles(corePluginsDir, "jar");
- }
-
- public List getBundledPlugins() {
- File corePluginsDir = new File(getHomeDir(), "lib/bundled-plugins");
- return getFiles(corePluginsDir, "jar");
+ public File getInstalledPluginsDir() {
+ return new File(getHomeDir(), "extensions/plugins");
}
- public List getUserPlugins() {
- File pluginsDir = getUserPluginsDir();
- return getFiles(pluginsDir, "jar");
+ public File getBundledPluginsDir() {
+ return new File(getHomeDir(), "lib/bundled-plugins");
}
- public File getUserPluginsDir() {
- return new File(getHomeDir(), "extensions/plugins");
+ public File getCorePluginsDir() {
+ return new File(getHomeDir(), "lib/core-plugins");
}
public File getDeprecatedPluginsDir() {
@@ -172,7 +161,7 @@ public class DefaultServerFileSystem implements ServerFileSystem, Startable {
}
private List getFiles(File dir, String... fileSuffixes) {
- List files = new ArrayList();
+ List files = new ArrayList<>();
if (dir != null && dir.exists()) {
if (fileSuffixes != null && fileSuffixes.length > 0) {
files.addAll(FileUtils.listFiles(dir, fileSuffixes, false));
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
index 5d857910be2..4f28227339e 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
@@ -19,16 +19,17 @@
*/
package org.sonar.server.platform;
-import java.util.Collection;
-import java.util.Properties;
-import javax.annotation.CheckForNull;
-import javax.servlet.ServletContext;
-import org.sonar.api.platform.ComponentContainer;
+import org.sonar.core.platform.ComponentContainer;
import org.sonar.api.platform.Server;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.persistence.DatabaseVersion;
+import javax.annotation.CheckForNull;
+import javax.servlet.ServletContext;
+import java.util.Collection;
+import java.util.Properties;
+
/**
* @since 2.2
*/
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/RailsAppsDeployer.java b/server/sonar-server/src/main/java/org/sonar/server/platform/RailsAppsDeployer.java
index c034a78ee38..8f7cb251897 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/RailsAppsDeployer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/RailsAppsDeployer.java
@@ -25,11 +25,11 @@ import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.picocontainer.Startable;
import org.sonar.api.Plugin;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
import org.sonar.api.platform.ServerFileSystem;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
import javax.annotation.Nullable;
@@ -47,28 +47,26 @@ public class RailsAppsDeployer implements Startable {
private static final Logger LOG = Loggers.get(RailsAppsDeployer.class);
private static final String ROR_PATH = "org/sonar/ror/";
- private final ServerFileSystem fileSystem;
+ private final ServerFileSystem fs;
private final PluginRepository pluginRepository;
- public RailsAppsDeployer(ServerFileSystem fileSystem, PluginRepository pluginRepository) {
- this.fileSystem = fileSystem;
+ public RailsAppsDeployer(ServerFileSystem fs, PluginRepository pluginRepository) {
+ this.fs = fs;
this.pluginRepository = pluginRepository;
}
@Override
public void start() {
- LOG.info("Deploy Ruby on Rails applications");
+ LOG.info("Deploying Ruby on Rails applications");
File appsDir = prepareRailsDirectory();
- for (PluginMetadata pluginMetadata : pluginRepository.getMetadata()) {
- String pluginKey = pluginMetadata.getKey();
- Plugin plugin = pluginRepository.getPlugin(pluginKey);
- if (plugin != null) {
- try {
- deployRailsApp(appsDir, pluginKey, plugin.getClass().getClassLoader());
- } catch (Exception e) {
- throw new IllegalStateException("Fail to deploy Ruby on Rails application: " + pluginKey, e);
- }
+ for (PluginInfo pluginInfo : pluginRepository.getPluginInfos()) {
+ String pluginKey = pluginInfo.getKey();
+ Plugin plugin = pluginRepository.getPluginInstance(pluginKey);
+ try {
+ deployRailsApp(appsDir, pluginKey, plugin.getClass().getClassLoader());
+ } catch (Exception e) {
+ throw new IllegalStateException(String.format("Fail to deploy Ruby on Rails application of plugin [%s]", pluginKey), e);
}
}
}
@@ -80,7 +78,7 @@ public class RailsAppsDeployer implements Startable {
@VisibleForTesting
File prepareRailsDirectory() {
- File appsDir = new File(fileSystem.getTempDir(), "ror");
+ File appsDir = new File(fs.getTempDir(), "ror");
prepareDir(appsDir);
return appsDir;
}
@@ -88,7 +86,7 @@ public class RailsAppsDeployer implements Startable {
@VisibleForTesting
static void deployRailsApp(File appsDir, final String pluginKey, ClassLoader appClassLoader) {
if (hasRailsApp(pluginKey, appClassLoader)) {
- LOG.info("Deploy app: " + pluginKey);
+ LOG.info("Deploying app: " + pluginKey);
File appDir = new File(appsDir, pluginKey);
ClassLoaderUtils.copyResources(appClassLoader, pathToRubyInitFile(pluginKey), appDir, new Function() {
@Override
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
index b6347f84e61..6844878d9b9 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
@@ -22,7 +22,6 @@ package org.sonar.server.platform;
import com.google.common.collect.Lists;
import org.sonar.api.config.EmailSettings;
import org.sonar.api.issue.action.Actions;
-import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.profiles.AnnotationProfileParser;
import org.sonar.api.profiles.XMLProfileParser;
import org.sonar.api.profiles.XMLProfileSerializer;
@@ -58,6 +57,8 @@ import org.sonar.core.persistence.DefaultDatabase;
import org.sonar.core.persistence.MyBatis;
import org.sonar.core.persistence.SemaphoreUpdater;
import org.sonar.core.persistence.SemaphoresImpl;
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.PluginLoader;
import org.sonar.core.purge.PurgeProfiler;
import org.sonar.core.qualitygate.db.ProjectQgateAssociationDao;
import org.sonar.core.qualitygate.db.QualityGateConditionDao;
@@ -216,9 +217,8 @@ import org.sonar.server.platform.ws.UpgradesSystemWsAction;
import org.sonar.server.plugins.InstalledPluginReferentialFactory;
import org.sonar.server.plugins.PluginDownloader;
import org.sonar.server.plugins.ServerExtensionInstaller;
-import org.sonar.server.plugins.ServerPluginJarInstaller;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
import org.sonar.server.plugins.ServerPluginRepository;
+import org.sonar.server.plugins.ServerPluginUnzipper;
import org.sonar.server.plugins.UpdateCenterClient;
import org.sonar.server.plugins.UpdateCenterMatrixFactory;
import org.sonar.server.plugins.ws.AvailablePluginsWsAction;
@@ -519,10 +519,10 @@ class ServerComponents {
PlatformRubyBridge.class,
// plugins
- ServerPluginJarsInstaller.class,
- ServerPluginJarInstaller.class,
- InstalledPluginReferentialFactory.class,
ServerPluginRepository.class,
+ ServerPluginUnzipper.class,
+ PluginLoader.class,
+ InstalledPluginReferentialFactory.class,
ServerExtensionInstaller.class,
// depends on plugins
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java
index 9ec58dc4044..591168f2831 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java
@@ -22,12 +22,13 @@ package org.sonar.server.platform.monitoring;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
+import org.sonar.updatecenter.common.Version;
+
+import javax.annotation.Nonnull;
import java.util.LinkedHashMap;
-import java.util.List;
/**
* Installed plugins (excluding core plugins)
@@ -47,21 +48,24 @@ public class PluginsMonitor implements Monitor {
@Override
public LinkedHashMap attributes() {
LinkedHashMap attributes = new LinkedHashMap<>();
- for (PluginMetadata plugin : plugins()) {
+ for (PluginInfo plugin : plugins()) {
LinkedHashMap pluginAttributes = new LinkedHashMap<>();
pluginAttributes.put("Name", plugin.getName());
- pluginAttributes.put("Version", plugin.getVersion());
+ Version version = plugin.getVersion();
+ if (version != null) {
+ pluginAttributes.put("Version", version.getName());
+ }
attributes.put(plugin.getKey(), pluginAttributes);
}
return attributes;
}
- private List plugins() {
- return Lists.newArrayList(Iterables.filter(repository.getMetadata(), new Predicate() {
+ private Iterable plugins() {
+ return Iterables.filter(repository.getPluginInfos(), new Predicate() {
@Override
- public boolean apply(PluginMetadata input) {
- return !input.isCore();
+ public boolean apply(@Nonnull PluginInfo info) {
+ return !info.isCore();
}
- }));
+ });
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/InstalledPluginReferentialFactory.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/InstalledPluginReferentialFactory.java
index 257cd22ca05..599899c475c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/InstalledPluginReferentialFactory.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/InstalledPluginReferentialFactory.java
@@ -20,7 +20,7 @@
package org.sonar.server.plugins;
import org.picocontainer.Startable;
-import org.sonar.api.platform.PluginRepository;
+import org.sonar.core.platform.PluginRepository;
import org.sonar.updatecenter.common.PluginReferential;
public class InstalledPluginReferentialFactory implements Startable {
@@ -51,7 +51,7 @@ public class InstalledPluginReferentialFactory implements Startable {
}
private void init() {
- installedPluginReferential = PluginReferentialMetadataConverter.getInstalledPluginReferential(pluginRepository.getMetadata());
+ installedPluginReferential = PluginReferentialMetadataConverter.getInstalledPluginReferential(pluginRepository.getPluginInfos());
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java
index 1e2dd190f49..b17ac977342 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java
@@ -25,7 +25,7 @@ import org.sonar.api.utils.HttpDownloader;
import org.sonar.api.utils.SonarException;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.core.platform.PluginInfo;
import org.sonar.server.platform.DefaultServerFileSystem;
import org.sonar.updatecenter.common.Release;
import org.sonar.updatecenter.common.Version;
@@ -48,6 +48,10 @@ import static org.apache.commons.io.FileUtils.forceMkdir;
import static org.apache.commons.io.FileUtils.toFile;
import static org.apache.commons.lang.StringUtils.substringAfterLast;
+/**
+ * Downloads plugins from update center. Files are copied in the directory extensions/downloads and then
+ * moved to extensions/plugins after server restart.
+ */
public class PluginDownloader implements Startable {
private static final Logger LOG = Loggers.get(PluginDownloader.class);
@@ -56,21 +60,17 @@ public class PluginDownloader implements Startable {
private final UpdateCenterMatrixFactory updateCenterMatrixFactory;
private final HttpDownloader downloader;
- private final ServerPluginJarInstaller installer;
private final File downloadDir;
public PluginDownloader(UpdateCenterMatrixFactory updateCenterMatrixFactory, HttpDownloader downloader,
- DefaultServerFileSystem fileSystem, ServerPluginJarInstaller installer) {
+ DefaultServerFileSystem fileSystem) {
this.updateCenterMatrixFactory = updateCenterMatrixFactory;
this.downloader = downloader;
- this.installer = installer;
this.downloadDir = fileSystem.getDownloadedPluginsDir();
}
/**
- * Delete the temporary files remaining from previous downloads
- *
- * @see #downloadRelease(org.sonar.updatecenter.common.Release)
+ * Deletes the temporary files remaining from previous downloads
*/
@Override
public void start() {
@@ -112,10 +112,10 @@ public class PluginDownloader implements Startable {
}
/**
- * @return the list of download plugins as {@link DefaultPluginMetadata} instances
+ * @return the list of download plugins as {@link PluginInfo} instances
*/
- public Collection getDownloadedPlugins() {
- return newArrayList(transform(listPlugins(this.downloadDir), installer.fileToPlugin()));
+ public Collection getDownloadedPlugins() {
+ return newArrayList(transform(listPlugins(this.downloadDir), PluginInfo.JarToPluginInfo.INSTANCE));
}
public void download(String pluginKey, Version version) {
@@ -154,10 +154,10 @@ public class PluginDownloader implements Startable {
}
private static Collection listTempFile(File dir) {
- return FileUtils.listFiles(dir, new String[]{TMP_SUFFIX}, false);
+ return FileUtils.listFiles(dir, new String[] {TMP_SUFFIX}, false);
}
private static Collection listPlugins(File dir) {
- return FileUtils.listFiles(dir, new String[]{PLUGIN_EXTENSION}, false);
+ return FileUtils.listFiles(dir, new String[] {PLUGIN_EXTENSION}, false);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginReferentialMetadataConverter.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginReferentialMetadataConverter.java
index 30646c02a95..70afcb42068 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginReferentialMetadataConverter.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginReferentialMetadataConverter.java
@@ -19,10 +19,11 @@
*/
package org.sonar.server.plugins;
-import org.sonar.api.platform.PluginMetadata;
+import org.sonar.core.platform.PluginInfo;
import org.sonar.updatecenter.common.PluginManifest;
import org.sonar.updatecenter.common.PluginReferential;
import org.sonar.updatecenter.common.PluginReferentialManifestConverter;
+import org.sonar.updatecenter.common.Version;
import java.util.Collection;
import java.util.List;
@@ -35,14 +36,14 @@ public class PluginReferentialMetadataConverter {
// Only static call
}
- public static PluginReferential getInstalledPluginReferential(Collection metadata) {
+ public static PluginReferential getInstalledPluginReferential(Collection metadata) {
List pluginManifestList = getPluginManifestList(metadata);
return PluginReferentialManifestConverter.fromPluginManifests(pluginManifestList);
}
- private static List getPluginManifestList(Collection metadata) {
+ private static List getPluginManifestList(Collection metadata) {
List pluginManifestList = newArrayList();
- for (PluginMetadata plugin : metadata) {
+ for (PluginInfo plugin : metadata) {
if (!plugin.isCore()) {
pluginManifestList.add(toPluginManifest(plugin));
}
@@ -50,20 +51,23 @@ public class PluginReferentialMetadataConverter {
return pluginManifestList;
}
- private static PluginManifest toPluginManifest(PluginMetadata metadata) {
+ private static PluginManifest toPluginManifest(PluginInfo metadata) {
PluginManifest pluginManifest = new PluginManifest();
pluginManifest.setKey(metadata.getKey());
pluginManifest.setName(metadata.getName());
- pluginManifest.setVersion(metadata.getVersion());
+ Version version = metadata.getVersion();
+ if (version != null) {
+ pluginManifest.setVersion(version.getName());
+ }
pluginManifest.setDescription(metadata.getDescription());
pluginManifest.setMainClass(metadata.getMainClass());
- pluginManifest.setOrganization(metadata.getOrganization());
+ pluginManifest.setOrganization(metadata.getOrganizationName());
pluginManifest.setOrganizationUrl(metadata.getOrganizationUrl());
pluginManifest.setLicense(metadata.getLicense());
- pluginManifest.setHomepage(metadata.getHomepage());
+ pluginManifest.setHomepage(metadata.getHomepageUrl());
pluginManifest.setIssueTrackerUrl(metadata.getIssueTrackerUrl());
pluginManifest.setBasePlugin(metadata.getBasePlugin());
- pluginManifest.setRequirePlugins(metadata.getRequiredPlugins().toArray(new String []{}));
+ pluginManifest.setRequirePlugins(metadata.getRequiredPlugins().toArray(new String[] {}));
return pluginManifest;
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerExtensionInstaller.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerExtensionInstaller.java
index c084470711c..e9297de4353 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerExtensionInstaller.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerExtensionInstaller.java
@@ -24,40 +24,43 @@ import com.google.common.collect.ListMultimap;
import org.sonar.api.Extension;
import org.sonar.api.ExtensionProvider;
import org.sonar.api.Plugin;
+import org.sonar.api.ServerComponent;
import org.sonar.api.ServerExtension;
-import org.sonar.api.platform.ComponentContainer;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
import java.util.Map;
/**
- * This class adds to picocontainer the server extensions provided by plugins
+ * Loads the plugins server extensions and injects them to DI container
*/
-public class ServerExtensionInstaller {
- private PluginRepository pluginRepository;
+public class ServerExtensionInstaller implements ServerComponent {
+
+ private final PluginRepository pluginRepository;
public ServerExtensionInstaller(PluginRepository pluginRepository) {
this.pluginRepository = pluginRepository;
}
public void installExtensions(ComponentContainer container) {
- ListMultimap installedExtensionsByPlugin = ArrayListMultimap.create();
+ ListMultimap installedExtensionsByPlugin = ArrayListMultimap.create();
- for (PluginMetadata pluginMetadata : pluginRepository.getMetadata()) {
- Plugin plugin = pluginRepository.getPlugin(pluginMetadata.getKey());
- container.addExtension(pluginMetadata, plugin);
+ for (PluginInfo pluginInfo : pluginRepository.getPluginInfos()) {
+ String pluginKey = pluginInfo.getKey();
+ Plugin plugin = pluginRepository.getPluginInstance(pluginKey);
+ container.addExtension(pluginInfo, plugin);
for (Object extension : plugin.getExtensions()) {
- if (installExtension(container, pluginMetadata, extension, true) != null) {
- installedExtensionsByPlugin.put(pluginMetadata, extension);
+ if (installExtension(container, pluginInfo, extension, true) != null) {
+ installedExtensionsByPlugin.put(pluginInfo, extension);
} else {
- container.declareExtension(pluginMetadata, extension);
+ container.declareExtension(pluginInfo, extension);
}
}
}
- for (Map.Entry entry : installedExtensionsByPlugin.entries()) {
- PluginMetadata plugin = entry.getKey();
+ for (Map.Entry entry : installedExtensionsByPlugin.entries()) {
+ PluginInfo plugin = entry.getKey();
Object extension = entry.getValue();
if (isExtensionProvider(extension)) {
ExtensionProvider provider = (ExtensionProvider) container.getComponentByKey(extension);
@@ -66,25 +69,25 @@ public class ServerExtensionInstaller {
}
}
- private void installProvider(ComponentContainer container, PluginMetadata plugin, ExtensionProvider provider) {
+ private void installProvider(ComponentContainer container, PluginInfo pluginInfo, ExtensionProvider provider) {
Object obj = provider.provide();
if (obj != null) {
if (obj instanceof Iterable) {
for (Object ext : (Iterable) obj) {
- installExtension(container, plugin, ext, false);
+ installExtension(container, pluginInfo, ext, false);
}
} else {
- installExtension(container, plugin, obj, false);
+ installExtension(container, pluginInfo, obj, false);
}
}
}
- Object installExtension(ComponentContainer container, PluginMetadata pluginMetadata, Object extension, boolean acceptProvider) {
+ Object installExtension(ComponentContainer container, PluginInfo pluginInfo, Object extension, boolean acceptProvider) {
if (isType(extension, ServerExtension.class)) {
if (!acceptProvider && isExtensionProvider(extension)) {
throw new IllegalStateException("ExtensionProvider can not include providers itself: " + extension);
}
- container.addExtension(pluginMetadata, extension);
+ container.addExtension(pluginInfo, extension);
return extension;
}
return null;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginJarInstaller.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginJarInstaller.java
deleted file mode 100644
index 777a197defd..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginJarInstaller.java
+++ /dev/null
@@ -1,62 +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.server.plugins;
-
-import org.apache.commons.io.FileUtils;
-import org.sonar.api.utils.ZipUtils;
-import org.sonar.core.plugins.DefaultPluginMetadata;
-import org.sonar.core.plugins.PluginJarInstaller;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.zip.ZipEntry;
-
-public class ServerPluginJarInstaller extends PluginJarInstaller {
-
- public void installToDir(DefaultPluginMetadata metadata, File pluginBasedir) {
- try {
- File pluginFile = metadata.getFile();
- File deployedPlugin = copyPlugin(pluginBasedir, pluginFile);
- install(metadata, pluginBasedir, deployedPlugin);
- } catch (IOException e) {
- throw new IllegalStateException(FAIL_TO_INSTALL_PLUGIN + metadata, e);
- }
- }
-
- private File copyPlugin(File pluginBasedir, File pluginFile) throws IOException {
- FileUtils.forceMkdir(pluginBasedir);
- File targetFile = new File(pluginBasedir, pluginFile.getName());
- FileUtils.copyFile(pluginFile, targetFile);
- return targetFile;
- }
-
- @Override
- protected File extractPluginDependencies(File pluginFile, File pluginBasedir) throws IOException {
- ZipUtils.unzip(pluginFile, pluginBasedir, new LibFilter());
- return pluginBasedir;
- }
-
- private static final class LibFilter implements ZipUtils.ZipEntryFilter {
- @Override
- public boolean accept(ZipEntry entry) {
- return entry.getName().startsWith("META-INF/lib");
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginJarsInstaller.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginJarsInstaller.java
deleted file mode 100644
index 9b9ce32dc81..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginJarsInstaller.java
+++ /dev/null
@@ -1,286 +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.server.plugins;
-
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.collect.Maps;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.Server;
-import org.sonar.api.platform.ServerUpgradeStatus;
-import org.sonar.api.utils.MessageException;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.api.utils.log.Profiler;
-import org.sonar.core.plugins.DefaultPluginMetadata;
-import org.sonar.server.platform.DefaultServerFileSystem;
-import org.sonar.updatecenter.common.PluginReferential;
-
-import javax.annotation.Nonnull;
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static com.google.common.collect.Iterables.transform;
-import static com.google.common.collect.Lists.newArrayList;
-import static java.lang.String.format;
-import static org.apache.commons.io.FileUtils.cleanDirectory;
-import static org.apache.commons.io.FileUtils.copyFile;
-import static org.apache.commons.io.FileUtils.deleteDirectory;
-import static org.apache.commons.io.FileUtils.deleteQuietly;
-import static org.apache.commons.io.FileUtils.forceMkdir;
-import static org.apache.commons.io.FileUtils.listFiles;
-import static org.apache.commons.io.FileUtils.moveFile;
-import static org.apache.commons.io.FileUtils.moveFileToDirectory;
-import static org.apache.commons.lang.StringUtils.isNotBlank;
-
-public class ServerPluginJarsInstaller {
-
- private static final Logger LOG = Loggers.get(ServerPluginJarsInstaller.class);
- private static final String FILE_EXTENSION_JAR = "jar";
- private static final Joiner SLASH_JOINER = Joiner.on(" / ").skipNulls();
-
- private final Server server;
- private final DefaultServerFileSystem fs;
- private final ServerPluginJarInstaller installer;
- private final Map pluginByKeys = Maps.newHashMap();
- private final ServerUpgradeStatus serverUpgradeStatus;
- private static final Set BLACKLISTED_PLUGINS = new HashSet(Arrays.asList("scmactivity", "issuesreport"));
-
- public ServerPluginJarsInstaller(Server server, ServerUpgradeStatus serverUpgradeStatus,
- DefaultServerFileSystem fs, ServerPluginJarInstaller installer) {
- this.server = server;
- this.serverUpgradeStatus = serverUpgradeStatus;
- this.fs = fs;
- this.installer = installer;
- }
-
- public void install() {
- Profiler profiler = Profiler.create(LOG).startInfo("Install plugins");
- deleteTrash();
- loadInstalledPlugins();
- copyBundledPlugins();
- moveDownloadedPlugins();
- loadCorePlugins();
- deployPlugins();
- profiler.stopDebug();
- }
-
- private void deleteTrash() {
- File trashDir = fs.getTrashPluginsDir();
- try {
- if (trashDir.exists()) {
- deleteDirectory(trashDir);
- }
- } catch (IOException e) {
- throw new IllegalStateException("Fail to clean the plugin trash directory: " + trashDir, e);
- }
- }
-
- private void loadInstalledPlugins() {
- for (File file : fs.getUserPlugins()) {
- PluginMetadata metadata = installer.fileToPlugin().apply(file);
- if (isNotBlank(metadata.getKey())) {
- loadInstalledPlugin(metadata);
- }
- }
- }
-
- private void loadInstalledPlugin(PluginMetadata metadata) {
- if (BLACKLISTED_PLUGINS.contains(metadata.getKey())) {
- LOG.warn("Plugin {} is blacklisted. Please uninstall it.", metadata.getName());
- } else {
- PluginMetadata existing = pluginByKeys.put(metadata.getKey(), metadata);
- if (existing != null) {
- throw MessageException.of(format("Found two files for the same plugin '%s': %s and %s",
- metadata.getKey(), metadata.getFile().getName(), existing.getFile().getName()));
- }
- }
- }
-
- private void moveDownloadedPlugins() {
- if (fs.getDownloadedPluginsDir().exists()) {
- for (File sourceFile : listJarFiles(fs.getDownloadedPluginsDir())) {
- overridePlugin(sourceFile, true);
- }
- }
- }
-
- private void copyBundledPlugins() {
- if (serverUpgradeStatus.isFreshInstall()) {
- for (File sourceFile : fs.getBundledPlugins()) {
- PluginMetadata metadata = installer.fileToPlugin().apply(sourceFile);
- // lib/bundled-plugins should be copied only if the plugin is not already
- // available in extensions/plugins
- if (!pluginByKeys.containsKey(metadata.getKey())) {
- overridePlugin(sourceFile, false);
- }
- }
- }
- }
-
- private void overridePlugin(File sourceFile, boolean deleteSource) {
- File destDir = fs.getUserPluginsDir();
- File destFile = new File(destDir, sourceFile.getName());
- if (destFile.exists()) {
- // plugin with same filename already installed
- deleteQuietly(destFile);
- }
-
- try {
- if (deleteSource) {
- moveFile(sourceFile, destFile);
- } else {
- copyFile(sourceFile, destFile, true);
- }
- } catch (IOException e) {
- LOG.error(format("Fail to move or copy plugin: %s to %s",
- sourceFile.getAbsolutePath(), destFile.getAbsolutePath()), e);
- }
-
- PluginMetadata metadata = installer.fileToPlugin().apply(destFile);
- if (isNotBlank(metadata.getKey())) {
- PluginMetadata existing = pluginByKeys.put(metadata.getKey(), metadata);
- if (existing != null) {
- if (!existing.getFile().getName().equals(destFile.getName())) {
- deleteQuietly(existing.getFile());
- }
- LOG.info("Plugin " + metadata.getKey() + " replaced by new version");
- }
- }
- }
-
- private void loadCorePlugins() {
- for (File file : fs.getCorePlugins()) {
- PluginMetadata metadata = installer.fileToCorePlugin().apply(file);
- PluginMetadata existing = pluginByKeys.put(metadata.getKey(), metadata);
- if (existing != null) {
- throw new IllegalStateException("Found two plugins with the same key '" + metadata.getKey() + "': " + metadata.getFile().getName() + " and "
- + existing.getFile().getName());
- }
- }
- }
-
- public void uninstall(String pluginKey) {
- for (String key : getPluginReferential().findLastReleasesWithDependencies(pluginKey)) {
- uninstallPlugin(key);
- }
- }
-
- private void uninstallPlugin(String pluginKey) {
- PluginMetadata metadata = pluginByKeys.get(pluginKey);
- if (metadata != null && !metadata.isCore()) {
- try {
- File masterFile = new File(fs.getUserPluginsDir(), metadata.getFile().getName());
- moveFileToDirectory(masterFile, fs.getTrashPluginsDir(), true);
- } catch (IOException e) {
- throw new IllegalStateException("Fail to uninstall plugin: " + pluginKey, e);
- }
- }
- }
-
- public List getUninstalledPluginFilenames() {
- if (!fs.getTrashPluginsDir().exists()) {
- return Collections.emptyList();
- }
-
- return newArrayList(transform(listJarFiles(fs.getTrashPluginsDir()), FileToName.INSTANCE));
- }
-
- /**
- * @return the list of plugins to be uninstalled as {@link DefaultPluginMetadata} instances
- */
- public Collection getUninstalledPlugins() {
- if (!fs.getTrashPluginsDir().exists()) {
- return Collections.emptyList();
- }
-
- return newArrayList(transform(listJarFiles(fs.getTrashPluginsDir()), installer.fileToPlugin()));
- }
-
- public void cancelUninstalls() {
- if (fs.getTrashPluginsDir().exists()) {
- for (File file : listJarFiles(fs.getTrashPluginsDir())) {
- try {
- moveFileToDirectory(file, fs.getUserPluginsDir(), false);
- } catch (IOException e) {
- throw new IllegalStateException("Fail to cancel plugin uninstalls", e);
- }
- }
- }
- }
-
- private void deployPlugins() {
- for (PluginMetadata metadata : pluginByKeys.values()) {
- deploy((DefaultPluginMetadata) metadata);
- }
- }
-
- private void deploy(DefaultPluginMetadata plugin) {
- LOG.info("Deploy plugin {}", SLASH_JOINER.join(plugin.getName(), plugin.getVersion(), plugin.getImplementationBuild()));
-
- if (!plugin.isCompatibleWith(server.getVersion())) {
- throw MessageException.of(format(
- "Plugin %s needs a more recent version of SonarQube than %s. At least %s is expected",
- plugin.getKey(), server.getVersion(), plugin.getSonarVersion()));
- }
-
- try {
- File pluginDeployDir = new File(fs.getDeployedPluginsDir(), plugin.getKey());
- forceMkdir(pluginDeployDir);
- cleanDirectory(pluginDeployDir);
-
- installer.installToDir(plugin, pluginDeployDir);
- } catch (IOException e) {
- throw new IllegalStateException("Fail to deploy the plugin " + plugin, e);
- }
- }
-
- public Collection getMetadata() {
- return pluginByKeys.values();
- }
-
- public PluginMetadata getMetadata(String pluginKey) {
- return pluginByKeys.get(pluginKey);
- }
-
- private PluginReferential getPluginReferential() {
- return PluginReferentialMetadataConverter.getInstalledPluginReferential(getMetadata());
- }
-
- private static Collection listJarFiles(File pluginDir) {
- return listFiles(pluginDir, new String[] {FILE_EXTENSION_JAR}, false);
- }
-
- private enum FileToName implements Function {
- INSTANCE;
-
- @Override
- public String apply(@Nonnull File file) {
- return file.getName();
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java
index 16028617966..cb9db1f4042 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java
@@ -19,76 +19,361 @@
*/
package org.sonar.server.plugins;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Ordering;
+import org.apache.commons.io.FileUtils;
import org.picocontainer.Startable;
-import org.sonar.api.utils.log.Loggers;
import org.sonar.api.Plugin;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
-import org.sonar.core.plugins.PluginClassloaders;
+import org.sonar.api.platform.Server;
+import org.sonar.api.platform.ServerUpgradeStatus;
+import org.sonar.api.utils.MessageException;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginLoader;
+import org.sonar.core.platform.PluginRepository;
+import org.sonar.server.platform.DefaultServerFileSystem;
+
+import javax.annotation.Nonnull;
-import javax.annotation.CheckForNull;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Lists.newArrayList;
+import static java.lang.String.format;
+import static org.apache.commons.io.FileUtils.copyFile;
+import static org.apache.commons.io.FileUtils.deleteQuietly;
+import static org.apache.commons.io.FileUtils.moveFile;
+import static org.apache.commons.io.FileUtils.moveFileToDirectory;
/**
- * This class loads JAR files and initializes classloaders of plugins
+ * Manages installation and loading of plugins:
+ *
+ * - installation of bundled plugins on first server startup
+ * - installation of new plugins (effective after server startup)
+ * - un-installation of plugins (effective after server startup)
+ * - cancel pending installations/un-installations
+ * - load plugin bytecode
+ *
*/
public class ServerPluginRepository implements PluginRepository, Startable {
- private final ServerPluginJarsInstaller jarsInstaller;
- private final PluginClassloaders classloaders;
- private Map pluginsByKey;
+ private static final Logger LOG = Loggers.get(ServerPluginRepository.class);
+ private static final String FILE_EXTENSION_JAR = "jar";
+ private static final Set DEFAULT_BLACKLISTED_PLUGINS = ImmutableSet.of("scmactivity", "issuesreport");
+ private static final Joiner SLASH_JOINER = Joiner.on(" / ").skipNulls();
+
+ private final Server server;
+ private final DefaultServerFileSystem fs;
+ private final ServerUpgradeStatus upgradeStatus;
+ private final PluginLoader loader;
+ private Set blacklistedPluginKeys = DEFAULT_BLACKLISTED_PLUGINS;
- public ServerPluginRepository(ServerPluginJarsInstaller jarsInstaller) {
- this.classloaders = new PluginClassloaders(getClass().getClassLoader());
- this.jarsInstaller = jarsInstaller;
+ // following fields are available after startup
+ private final Map pluginInfosByKeys = new HashMap<>();
+ private final Map pluginInstancesByKeys = new HashMap<>();
+
+ public ServerPluginRepository(Server server, ServerUpgradeStatus upgradeStatus,
+ DefaultServerFileSystem fs, PluginLoader loader) {
+ this.server = server;
+ this.upgradeStatus = upgradeStatus;
+ this.fs = fs;
+ this.loader = loader;
+ }
+
+ @VisibleForTesting
+ void setBlacklistedPluginKeys(Set keys) {
+ this.blacklistedPluginKeys = keys;
}
@Override
public void start() {
- jarsInstaller.install();
- Collection metadata = jarsInstaller.getMetadata();
- pluginsByKey = classloaders.init(metadata);
+ loadPreInstalledPlugins();
+ copyBundledPlugins();
+ moveDownloadedPlugins();
+ loadCorePlugins();
+ unloadIncompatiblePlugins();
+ logInstalledPlugins();
+ loadInstances();
}
@Override
public void stop() {
- classloaders.clean();
+ // close classloaders
+ loader.unload(pluginInstancesByKeys.values());
+
+ pluginInstancesByKeys.clear();
+ pluginInfosByKeys.clear();
}
- @Override
- public Plugin getPlugin(String key) {
- return pluginsByKey.get(key);
+ /**
+ * Load the plugins that are located in extensions/plugins. Blacklisted plugins are
+ * deleted.
+ */
+ private void loadPreInstalledPlugins() {
+ for (File file : listJarFiles(fs.getInstalledPluginsDir())) {
+ PluginInfo info = PluginInfo.create(file);
+ registerPluginInfo(info);
+ }
+ }
+
+ /**
+ * Move the plugins recently downloaded to extensions/plugins.
+ */
+ private void moveDownloadedPlugins() {
+ if (fs.getDownloadedPluginsDir().exists()) {
+ for (File sourceFile : listJarFiles(fs.getDownloadedPluginsDir())) {
+ overrideAndRegisterPlugin(sourceFile, true);
+ }
+ }
+ }
+
+ /**
+ * Copies the plugins bundled with SonarQube distribution to directory extensions/plugins.
+ * Does nothing if not a fresh installation.
+ */
+ private void copyBundledPlugins() {
+ if (upgradeStatus.isFreshInstall()) {
+ for (File sourceFile : listJarFiles(fs.getBundledPluginsDir())) {
+ PluginInfo info = PluginInfo.create(sourceFile);
+ // lib/bundled-plugins should be copied only if the plugin is not already
+ // available in extensions/plugins
+ if (!pluginInfosByKeys.containsKey(info.getKey())) {
+ overrideAndRegisterPlugin(sourceFile, false);
+ }
+ }
+ }
+ }
+
+ private void registerPluginInfo(PluginInfo info) {
+ if (blacklistedPluginKeys.contains(info.getKey())) {
+ LOG.warn("Plugin {} [{}] is blacklisted and is being uninstalled.", info.getName(), info.getKey());
+ deleteQuietly(info.getFile());
+ return;
+ }
+ PluginInfo existing = pluginInfosByKeys.put(info.getKey(), info);
+ if (existing != null) {
+ throw MessageException.of(format("Found two files for the same plugin [%s]: %s and %s",
+ info.getKey(), info.getFile().getName(), existing.getFile().getName()));
+ }
+
+ }
+
+ /**
+ * Move or copy plugin to directory extensions/plugins. If a version of this plugin
+ * already exists then it's deleted.
+ */
+ private void overrideAndRegisterPlugin(File sourceFile, boolean deleteSource) {
+ File destDir = fs.getInstalledPluginsDir();
+ File destFile = new File(destDir, sourceFile.getName());
+ if (destFile.exists()) {
+ // plugin with same filename already installed
+ deleteQuietly(destFile);
+ }
+
+ try {
+ if (deleteSource) {
+ moveFile(sourceFile, destFile);
+ } else {
+ copyFile(sourceFile, destFile, true);
+ }
+ } catch (IOException e) {
+ LOG.error(format("Fail to move or copy plugin: %s to %s",
+ sourceFile.getAbsolutePath(), destFile.getAbsolutePath()), e);
+ }
+
+ PluginInfo info = PluginInfo.create(destFile);
+ PluginInfo existing = pluginInfosByKeys.put(info.getKey(), info);
+ if (existing != null) {
+ if (!existing.getFile().getName().equals(destFile.getName())) {
+ deleteQuietly(existing.getFile());
+ }
+ LOG.info("Plugin {} [{}] updated to version {}", info.getName(), info.getKey(), info.getVersion());
+ } else {
+ LOG.info("Plugin {} [{}] installed", info.getName(), info.getKey());
+ }
+ }
+
+ private void loadCorePlugins() {
+ for (File file : listJarFiles(fs.getCorePluginsDir())) {
+ PluginInfo info = PluginInfo.create(file).setCore(true);
+ registerPluginInfo(info);
+ }
+ }
+
+ /**
+ * Removes the plugins that are not compatible with current environment. In some cases
+ * plugin files can be deleted.
+ */
+ private void unloadIncompatiblePlugins() {
+ // loop as long as the previous loop ignored some plugins. That allows to support dependencies
+ // on many levels, for example D extends C, which extends B, which requires A. If A is not installed,
+ // then B, C and D must be ignored. That's not possible to achieve this algorithm with a single
+ // iteration over plugins.
+ List removedKeys = new ArrayList<>();
+ do {
+ removedKeys.clear();
+ for (PluginInfo plugin : pluginInfosByKeys.values()) {
+ if (!Strings.isNullOrEmpty(plugin.getBasePlugin()) && !pluginInfosByKeys.containsKey(plugin.getBasePlugin())) {
+ // this plugin extends a plugin that is not installed
+ LOG.warn("Plugin {} [{}] is ignored because its base plugin [{}] is not installed", plugin.getName(), plugin.getKey(), plugin.getBasePlugin());
+ removedKeys.add(plugin.getKey());
+ }
+
+ if (!plugin.isCompatibleWith(server.getVersion())) {
+ LOG.warn("Plugin {} [{}] is ignored because it requires at least SonarQube {}", plugin.getName(), plugin.getKey(), plugin.getMinimalSqVersion());
+ removedKeys.add(plugin.getKey());
+ }
+
+ for (PluginInfo.RequiredPlugin requiredPlugin : plugin.getRequiredPlugins()) {
+ PluginInfo available = pluginInfosByKeys.get(requiredPlugin.getKey());
+ if (available == null) {
+ // this plugin requires a plugin that is not installed
+ LOG.warn("Plugin {} [{}] is ignored because the required plugin [{}] is not installed", plugin.getName(), plugin.getKey(), requiredPlugin.getKey());
+ removedKeys.add(plugin.getKey());
+ } else if (requiredPlugin.getMinimalVersion().compareToIgnoreQualifier(available.getVersion()) > 0) {
+ LOG.warn("Plugin {} [{}] is ignored because the version {}Â of required plugin [{}] is not supported", plugin.getName(), plugin.getKey(),
+ requiredPlugin.getKey(), requiredPlugin.getMinimalVersion());
+ removedKeys.add(plugin.getKey());
+ }
+ }
+ }
+ for (String removedKey : removedKeys) {
+ pluginInfosByKeys.remove(removedKey);
+ }
+ } while (!removedKeys.isEmpty());
+ }
+
+ private void logInstalledPlugins() {
+ List orderedPlugins = Ordering.natural().sortedCopy(pluginInfosByKeys.values());
+ for (PluginInfo plugin : orderedPlugins) {
+ LOG.info("Plugin: {}", SLASH_JOINER.join(plugin.getName(), plugin.getVersion(), plugin.getImplementationBuild()));
+ }
}
- @CheckForNull
- public ClassLoader getClassLoader(String pluginKey) {
- return classloaders.get(pluginKey);
+ private void loadInstances() {
+ pluginInstancesByKeys.clear();
+ pluginInstancesByKeys.putAll(loader.load(pluginInfosByKeys));
}
- @CheckForNull
- public Class getClass(String pluginKey, String classname) {
- Class clazz = null;
- ClassLoader classloader = getClassLoader(pluginKey);
- if (classloader != null) {
+ /**
+ * Uninstall a plugin and its dependents (the plugins that require the plugin to be uninstalled)
+ */
+ public void uninstall(String pluginKey) {
+ for (PluginInfo otherPlugin : pluginInfosByKeys.values()) {
+ if (!otherPlugin.getKey().equals(pluginKey)) {
+ for (PluginInfo.RequiredPlugin requiredPlugin : otherPlugin.getRequiredPlugins()) {
+ if (requiredPlugin.getKey().equals(pluginKey)) {
+ uninstall(otherPlugin.getKey());
+ }
+ }
+ }
+ }
+
+ PluginInfo info = pluginInfosByKeys.get(pluginKey);
+ if (!info.isCore()) {
try {
- clazz = classloader.loadClass(classname);
+ // we don't reuse info.getFile() just to be sure that file is located in from extensions/plugins
+ File masterFile = new File(fs.getInstalledPluginsDir(), info.getFile().getName());
+ moveFileToDirectory(masterFile, uninstalledPluginsDir(), true);
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to uninstall plugin [" + pluginKey + "]", e);
+ }
+ }
+ }
+
+ public List getUninstalledPluginFilenames() {
+ return newArrayList(transform(listJarFiles(uninstalledPluginsDir()), FileToName.INSTANCE));
+ }
- } catch (ClassNotFoundException e) {
- Loggers.get(getClass()).warn("Class not found in plugin " + pluginKey + ": " + classname, e);
+ /**
+ * @return the list of plugins to be uninstalled as {@link PluginInfo} instances
+ */
+ public Collection getUninstalledPlugins() {
+ return newArrayList(transform(listJarFiles(uninstalledPluginsDir()), PluginInfo.JarToPluginInfo.INSTANCE));
+ }
+
+ public void cancelUninstalls() {
+ for (File file : listJarFiles(uninstalledPluginsDir())) {
+ try {
+ moveFileToDirectory(file, fs.getInstalledPluginsDir(), false);
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to cancel plugin uninstalls", e);
}
}
- return clazz;
+ }
+
+ public Map getPluginInfosByKeys() {
+ return pluginInfosByKeys;
+ }
+
+ @Override
+ public Collection getPluginInfos() {
+ return pluginInfosByKeys.values();
+ }
+
+ @Override
+ public PluginInfo getPluginInfo(String key) {
+ PluginInfo info = pluginInfosByKeys.get(key);
+ if (info == null) {
+ throw new IllegalArgumentException(String.format("Plugin [%s] does not exist", key));
+ }
+ return info;
}
@Override
- public Collection getMetadata() {
- return jarsInstaller.getMetadata();
+ public Plugin getPluginInstance(String key) {
+ Plugin plugin = pluginInstancesByKeys.get(key);
+ if (plugin == null) {
+ throw new IllegalArgumentException(String.format("Plugin [%s] does not exist", key));
+ }
+ return plugin;
}
@Override
- public PluginMetadata getMetadata(String pluginKey) {
- return jarsInstaller.getMetadata(pluginKey);
+ public boolean hasPlugin(String key) {
+ return pluginInfosByKeys.containsKey(key);
}
+ private enum FileToName implements Function {
+ INSTANCE;
+
+ @Override
+ public String apply(@Nonnull File file) {
+ return file.getName();
+ }
+
+ }
+
+ /**
+ * @return existing trash dir
+ */
+ private File uninstalledPluginsDir() {
+ File dir = new File(fs.getTempDir(), "uninstalled-plugins");
+ try {
+ FileUtils.forceMkdir(dir);
+ return dir;
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to create temp directory: " + dir.getAbsolutePath(), e);
+ }
+ }
+
+ private static Collection listJarFiles(File dir) {
+ if (dir.exists()) {
+ return FileUtils.listFiles(dir, new String[] {FILE_EXTENSION_JAR}, false);
+ }
+ return Collections.emptyList();
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginUnzipper.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginUnzipper.java
new file mode 100644
index 00000000000..59bc5a850fa
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginUnzipper.java
@@ -0,0 +1,65 @@
+/*
+ * 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.server.plugins;
+
+import org.apache.commons.io.FileUtils;
+import org.sonar.api.ServerComponent;
+import org.sonar.api.utils.ZipUtils;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginUnzipper;
+import org.sonar.core.platform.UnzippedPlugin;
+import org.sonar.server.platform.DefaultServerFileSystem;
+
+import java.io.File;
+
+import static org.apache.commons.io.FileUtils.cleanDirectory;
+import static org.apache.commons.io.FileUtils.forceMkdir;
+
+public class ServerPluginUnzipper extends PluginUnzipper implements ServerComponent {
+
+ private final DefaultServerFileSystem fs;
+
+ public ServerPluginUnzipper(DefaultServerFileSystem fs) {
+ this.fs = fs;
+ }
+
+ /**
+ * JAR files of directory extensions/plugins can be moved when server is up and plugins are uninstalled.
+ * For this reason these files must not be locked by classloaders. They are copied to the directory
+ * web/deploy/plugins in order to be loaded by {@link org.sonar.core.platform.PluginLoader}.
+ */
+ @Override
+ public UnzippedPlugin unzip(PluginInfo pluginInfo) {
+ File toDir = new File(fs.getDeployedPluginsDir(), pluginInfo.getKey());
+ try {
+ forceMkdir(toDir);
+ cleanDirectory(toDir);
+
+ File jarSource = pluginInfo.getFile();
+ File jarTarget = new File(toDir, jarSource.getName());
+ FileUtils.copyFile(jarSource, jarTarget);
+ ZipUtils.unzip(jarSource, toDir, newLibFilter());
+ return UnzippedPlugin.createFromUnzippedDir(pluginInfo.getKey(), jarTarget, toDir);
+ } catch (Exception e) {
+ throw new IllegalStateException(String.format(
+ "Fail to unzip plugin [%s] %s to %s", pluginInfo.getKey(), pluginInfo.getFile().getAbsolutePath(), toDir.getAbsolutePath()), e);
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java
index 8d24a1ae5f0..9a7ab9c3690 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java
@@ -22,8 +22,10 @@ package org.sonar.server.plugins;
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
+import org.sonar.api.Plugin;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonar.core.platform.PluginRepository;
import org.sonar.server.platform.Platform;
import javax.servlet.ServletException;
@@ -45,29 +47,25 @@ public class StaticResourcesServlet extends HttpServlet {
String pluginKey = getPluginKey(request);
String resource = getResourcePath(request);
- ServerPluginRepository pluginRepository = Platform.getInstance().getContainer().getComponentByType(ServerPluginRepository.class);
- ClassLoader classLoader = pluginRepository.getClassLoader(pluginKey);
- if (classLoader == null) {
- LOG.error("Plugin not found: " + pluginKey);
+ PluginRepository pluginRepository = Platform.getInstance().getContainer().getComponentByType(PluginRepository.class);
+ if (!pluginRepository.hasPlugin(pluginKey)) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
InputStream in = null;
OutputStream out = null;
try {
- in = classLoader.getResourceAsStream(resource);
+ in = pluginRepository.getPluginInstance(pluginKey).getClass().getClassLoader().getResourceAsStream(resource);
if (in != null) {
// mime type must be set before writing response body
completeContentType(response, resource);
out = response.getOutputStream();
IOUtils.copy(in, out);
-
} else {
- LOG.error("Unable to find resource '" + resource + "' in plugin '" + pluginKey + "'");
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} catch (Exception e) {
- LOG.error("Unable to load static resource '" + resource + "' from plugin '" + pluginKey + "'", e);
+ LOG.error(String.format("Unable to load resource [%s] from plugin [%s]", resource, pluginKey), e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} finally {
IOUtils.closeQuietly(in);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/CancelAllPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/CancelAllPluginsWsAction.java
index 93124251589..3899e50985d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/CancelAllPluginsWsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/CancelAllPluginsWsAction.java
@@ -24,17 +24,17 @@ import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
+import org.sonar.server.plugins.ServerPluginRepository;
import org.sonar.server.user.UserSession;
public class CancelAllPluginsWsAction implements PluginsWsAction {
private final PluginDownloader pluginDownloader;
- private final ServerPluginJarsInstaller pluginJarsInstaller;
+ private final ServerPluginRepository pluginRepository;
- public CancelAllPluginsWsAction(PluginDownloader pluginDownloader, ServerPluginJarsInstaller pluginJarsInstaller) {
+ public CancelAllPluginsWsAction(PluginDownloader pluginDownloader, ServerPluginRepository pluginRepository) {
this.pluginDownloader = pluginDownloader;
- this.pluginJarsInstaller = pluginJarsInstaller;
+ this.pluginRepository = pluginRepository;
}
@Override
@@ -52,7 +52,7 @@ public class CancelAllPluginsWsAction implements PluginsWsAction {
UserSession.get().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
pluginDownloader.cancelDownloads();
- pluginJarsInstaller.cancelUninstalls();
+ pluginRepository.cancelUninstalls();
response.noContent();
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java
index c84b730c96c..dc2f3ff4be7 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java
@@ -22,14 +22,15 @@ package org.sonar.server.plugins.ws;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.io.Resources;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.server.plugins.ServerPluginRepository;
import javax.annotation.Nullable;
+
import java.util.Collection;
import java.util.SortedSet;
@@ -42,10 +43,10 @@ import static org.sonar.server.plugins.ws.PluginWSCommons.NAME_KEY_PLUGIN_METADA
public class InstalledPluginsWsAction implements PluginsWsAction {
private static final String ARRAY_PLUGINS = "plugins";
- private final PluginRepository pluginRepository;
+ private final ServerPluginRepository pluginRepository;
private final PluginWSCommons pluginWSCommons;
- public InstalledPluginsWsAction(PluginRepository pluginRepository,
+ public InstalledPluginsWsAction(ServerPluginRepository pluginRepository,
PluginWSCommons pluginWSCommons) {
this.pluginRepository = pluginRepository;
this.pluginWSCommons = pluginWSCommons;
@@ -62,39 +63,39 @@ public class InstalledPluginsWsAction implements PluginsWsAction {
@Override
public void handle(Request request, Response response) throws Exception {
- Collection pluginMetadatas = retrieveAndSortPluginMetadata();
+ Collection infos = retrieveAndSortPluginMetadata();
JsonWriter jsonWriter = response.newJsonWriter();
jsonWriter.setSerializeEmptys(false);
jsonWriter.beginObject();
- writeMetadataList(jsonWriter, pluginMetadatas);
+ writeMetadataList(jsonWriter, infos);
jsonWriter.endObject();
jsonWriter.close();
}
- private SortedSet retrieveAndSortPluginMetadata() {
+ private SortedSet retrieveAndSortPluginMetadata() {
return ImmutableSortedSet.copyOf(
NAME_KEY_PLUGIN_METADATA_COMPARATOR,
- filter(pluginRepository.getMetadata(), NotCorePluginsPredicate.INSTANCE)
+ filter(pluginRepository.getPluginInfos(), NotCorePluginsPredicate.INSTANCE)
);
}
- private void writeMetadataList(JsonWriter jsonWriter, Collection pluginMetadatas) {
+ private void writeMetadataList(JsonWriter jsonWriter, Collection pluginMetadatas) {
jsonWriter.name(ARRAY_PLUGINS);
jsonWriter.beginArray();
- for (PluginMetadata pluginMetadata : pluginMetadatas) {
+ for (PluginInfo pluginMetadata : pluginMetadatas) {
pluginWSCommons.writePluginMetadata(jsonWriter, pluginMetadata);
}
jsonWriter.endArray();
}
- private enum NotCorePluginsPredicate implements Predicate {
+ private enum NotCorePluginsPredicate implements Predicate {
INSTANCE;
@Override
- public boolean apply(@Nullable PluginMetadata input) {
+ public boolean apply(@Nullable PluginInfo input) {
return input != null && !input.isCore();
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java
index 8c55caeaf68..29eb3cc9b53 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java
@@ -19,14 +19,13 @@
*/
package org.sonar.server.plugins.ws;
-import org.sonar.api.platform.PluginMetadata;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.core.platform.PluginInfo;
import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
+import org.sonar.server.plugins.ServerPluginRepository;
import java.util.Collection;
@@ -43,24 +42,24 @@ public class PendingPluginsWsAction implements PluginsWsAction {
private static final String ARRAY_REMOVING = "removing";
private final PluginDownloader pluginDownloader;
- private final ServerPluginJarsInstaller serverPluginJarsInstaller;
+ private final ServerPluginRepository installer;
private final PluginWSCommons pluginWSCommons;
public PendingPluginsWsAction(PluginDownloader pluginDownloader,
- ServerPluginJarsInstaller serverPluginJarsInstaller,
- PluginWSCommons pluginWSCommons) {
+ ServerPluginRepository installer,
+ PluginWSCommons pluginWSCommons) {
this.pluginDownloader = pluginDownloader;
- this.serverPluginJarsInstaller = serverPluginJarsInstaller;
+ this.installer = installer;
this.pluginWSCommons = pluginWSCommons;
}
@Override
public void define(WebService.NewController controller) {
controller.createAction("pending")
- .setDescription("Get the list of plugins which will either be installed or removed at the next startup of the SonarQube instance, sorted by plugin name")
- .setSince("5.2")
- .setHandler(this)
- .setResponseExample(getResource(this.getClass(), "example-pending_plugins.json"));
+ .setDescription("Get the list of plugins which will either be installed or removed at the next startup of the SonarQube instance, sorted by plugin name")
+ .setSince("5.2")
+ .setHandler(this)
+ .setResponseExample(getResource(this.getClass(), "example-pending_plugins.json"));
}
@Override
@@ -80,8 +79,8 @@ public class PendingPluginsWsAction implements PluginsWsAction {
private void writeInstalling(JsonWriter jsonWriter) {
jsonWriter.name(ARRAY_INSTALLING);
jsonWriter.beginArray();
- Collection plugins = pluginDownloader.getDownloadedPlugins();
- for (PluginMetadata pluginMetadata : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
+ Collection plugins = pluginDownloader.getDownloadedPlugins();
+ for (PluginInfo pluginMetadata : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
pluginWSCommons.writePluginMetadata(jsonWriter, pluginMetadata);
}
jsonWriter.endArray();
@@ -90,8 +89,8 @@ public class PendingPluginsWsAction implements PluginsWsAction {
private void writeRemoving(JsonWriter jsonWriter) {
jsonWriter.name(ARRAY_REMOVING);
jsonWriter.beginArray();
- Collection plugins = serverPluginJarsInstaller.getUninstalledPlugins();
- for (PluginMetadata pluginMetadata : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
+ Collection plugins = installer.getUninstalledPlugins();
+ for (PluginInfo pluginMetadata : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
pluginWSCommons.writePluginMetadata(jsonWriter, pluginMetadata);
}
jsonWriter.endArray();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginWSCommons.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginWSCommons.java
index 08cc27555b4..c2f8a8b6b63 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginWSCommons.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginWSCommons.java
@@ -24,13 +24,14 @@ import com.google.common.base.Function;
import com.google.common.collect.Ordering;
import java.util.Comparator;
import javax.annotation.Nonnull;
-import org.sonar.api.platform.PluginMetadata;
import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.platform.PluginInfo;
import org.sonar.updatecenter.common.Artifact;
import org.sonar.updatecenter.common.Plugin;
import org.sonar.updatecenter.common.PluginUpdate;
import org.sonar.updatecenter.common.Release;
import org.sonar.updatecenter.common.UpdateCenter;
+import org.sonar.updatecenter.common.Version;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
@@ -59,7 +60,7 @@ public class PluginWSCommons {
static final String PROPERTY_IMPLEMENTATION_BUILD = "implementationBuild";
static final String PROPERTY_CHANGE_LOG_URL = "changeLogUrl";
- public static final Ordering NAME_KEY_PLUGIN_METADATA_COMPARATOR = Ordering.natural()
+ public static final Ordering NAME_KEY_PLUGIN_METADATA_COMPARATOR = Ordering.natural()
.onResultOf(PluginMetadataToName.INSTANCE)
.compound(Ordering.natural().onResultOf(PluginMetadataToKey.INSTANCE));
public static final Comparator NAME_KEY_PLUGIN_ORDERING = Ordering.from(CASE_INSENSITIVE_ORDER)
@@ -70,23 +71,26 @@ public class PluginWSCommons {
public static final Comparator NAME_KEY_PLUGIN_UPDATE_ORDERING = Ordering.from(NAME_KEY_PLUGIN_ORDERING)
.onResultOf(PluginUpdateToPlugin.INSTANCE);
- public void writePluginMetadata(JsonWriter jsonWriter, PluginMetadata pluginMetadata) {
+ public void writePluginMetadata(JsonWriter jsonWriter, PluginInfo info) {
jsonWriter.beginObject();
- writeMetadata(jsonWriter, pluginMetadata);
+ writeMetadata(jsonWriter, info);
jsonWriter.endObject();
}
- public void writeMetadata(JsonWriter jsonWriter, PluginMetadata pluginMetadata) {
+ public void writeMetadata(JsonWriter jsonWriter, PluginInfo pluginMetadata) {
jsonWriter.prop(PROPERTY_KEY, pluginMetadata.getKey());
jsonWriter.prop(PROPERTY_NAME, pluginMetadata.getName());
jsonWriter.prop(PROPERTY_DESCRIPTION, pluginMetadata.getDescription());
- jsonWriter.prop(PROPERTY_VERSION, pluginMetadata.getVersion());
+ Version version = pluginMetadata.getVersion();
+ if (version != null) {
+ jsonWriter.prop(PROPERTY_VERSION, version.getName());
+ }
jsonWriter.prop(PROPERTY_LICENSE, pluginMetadata.getLicense());
- jsonWriter.prop(PROPERTY_ORGANIZATION_NAME, pluginMetadata.getOrganization());
+ jsonWriter.prop(PROPERTY_ORGANIZATION_NAME, pluginMetadata.getOrganizationName());
jsonWriter.prop(PROPERTY_ORGANIZATION_URL, pluginMetadata.getOrganizationUrl());
- jsonWriter.prop(PROPERTY_HOMEPAGE, pluginMetadata.getHomepage());
+ jsonWriter.prop(PROPERTY_HOMEPAGE, pluginMetadata.getHomepageUrl());
jsonWriter.prop(PROPERTY_ISSUE_TRACKER_URL, pluginMetadata.getIssueTrackerUrl());
jsonWriter.prop(PROPERTY_IMPLEMENTATION_BUILD, pluginMetadata.getImplementationBuild());
}
@@ -221,20 +225,20 @@ public class PluginWSCommons {
}
}
- private enum PluginMetadataToName implements Function {
+ private enum PluginMetadataToName implements Function {
INSTANCE;
@Override
- public String apply(@Nonnull PluginMetadata input) {
+ public String apply(@Nonnull PluginInfo input) {
return input.getName();
}
}
- private enum PluginMetadataToKey implements Function {
+ private enum PluginMetadataToKey implements Function {
INSTANCE;
@Override
- public String apply(@Nonnull PluginMetadata input) {
+ public String apply(@Nonnull PluginInfo input) {
return input.getKey();
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UninstallPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UninstallPluginsWsAction.java
index bb2e9e1c43a..98399499acd 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UninstallPluginsWsAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UninstallPluginsWsAction.java
@@ -19,18 +19,13 @@
*/
package org.sonar.server.plugins.ws;
-import com.google.common.base.Predicate;
-import javax.annotation.Nullable;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
+import org.sonar.server.plugins.ServerPluginRepository;
import org.sonar.server.user.UserSession;
-import static com.google.common.collect.Iterables.find;
import static java.lang.String.format;
/**
@@ -39,12 +34,10 @@ import static java.lang.String.format;
public class UninstallPluginsWsAction implements PluginsWsAction {
private static final String PARAM_KEY = "key";
- private final PluginRepository pluginRepository;
- private final ServerPluginJarsInstaller pluginJarsInstaller;
+ private final ServerPluginRepository pluginRepository;
- public UninstallPluginsWsAction(PluginRepository pluginRepository, ServerPluginJarsInstaller pluginJarsInstaller) {
+ public UninstallPluginsWsAction(ServerPluginRepository pluginRepository) {
this.pluginRepository = pluginRepository;
- this.pluginJarsInstaller = pluginJarsInstaller;
}
@Override
@@ -66,27 +59,14 @@ public class UninstallPluginsWsAction implements PluginsWsAction {
UserSession.get().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
String key = request.mandatoryParam(PARAM_KEY);
ensurePluginIsInstalled(key);
- pluginJarsInstaller.uninstall(key);
+ pluginRepository.uninstall(key);
response.noContent();
}
+ // FIXME should be moved to {@link ServerPluginRepository#uninstall(String)}
private void ensurePluginIsInstalled(String key) {
- if (find(pluginRepository.getMetadata(), new PluginKeyPredicate(key), null) == null) {
- throw new IllegalArgumentException(
- format("No plugin with key '%s' or plugin '%s' is not installed", key, key));
- }
- }
-
- private static class PluginKeyPredicate implements Predicate {
- private final String key;
-
- public PluginKeyPredicate(String key) {
- this.key = key;
- }
-
- @Override
- public boolean apply(@Nullable PluginMetadata input) {
- return input != null && key.equals(input.getKey());
+ if (!pluginRepository.hasPlugin(key)) {
+ throw new IllegalArgumentException(format("Plugin [%s] is not installed", key));
}
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/IndexQueue.java b/server/sonar-server/src/main/java/org/sonar/server/search/IndexQueue.java
index c29cd525cc9..d20d2c4e825 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/search/IndexQueue.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/search/IndexQueue.java
@@ -29,7 +29,7 @@ import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.sonar.api.ServerComponent;
-import org.sonar.api.platform.ComponentContainer;
+import org.sonar.core.platform.ComponentContainer;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.cluster.WorkQueue;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/startup/GeneratePluginIndex.java b/server/sonar-server/src/main/java/org/sonar/server/startup/GeneratePluginIndex.java
index d79adb553c2..4fe91fb829f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/startup/GeneratePluginIndex.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/startup/GeneratePluginIndex.java
@@ -22,9 +22,9 @@ 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.api.platform.PluginRepository;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.api.ServerComponent;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
import org.sonar.core.plugins.RemotePlugin;
import org.sonar.server.platform.DefaultServerFileSystem;
@@ -33,10 +33,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
-/**
- * @since 2.11
- */
-public final class GeneratePluginIndex {
+public final class GeneratePluginIndex implements ServerComponent {
private DefaultServerFileSystem fileSystem;
private PluginRepository repository;
@@ -54,8 +51,8 @@ public final class GeneratePluginIndex {
FileUtils.forceMkdir(indexFile.getParentFile());
Writer writer = new FileWriter(indexFile, false);
try {
- for (PluginMetadata metadata : repository.getMetadata()) {
- writer.append(RemotePlugin.create((DefaultPluginMetadata) metadata).marshal());
+ for (PluginInfo pluginInfo : repository.getPluginInfos()) {
+ writer.append(RemotePlugin.create(pluginInfo).marshal());
writer.append(CharUtils.LF);
}
writer.flush();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
index 4c2ed9deef1..71a39f1e1f9 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
@@ -27,13 +27,12 @@ import java.util.List;
import java.util.Map;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
+import org.sonar.api.Plugin;
import org.sonar.api.config.License;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.Settings;
-import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.platform.NewUserHandler;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.ResourceType;
import org.sonar.api.resources.ResourceTypes;
@@ -44,6 +43,9 @@ import org.sonar.api.web.RubyRailsWebservice;
import org.sonar.api.web.Widget;
import org.sonar.core.persistence.Database;
import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
import org.sonar.core.resource.ResourceIndexerDao;
import org.sonar.core.timemachine.Periods;
import org.sonar.process.ProcessProperties;
@@ -58,7 +60,6 @@ import org.sonar.server.platform.ServerSettings;
import org.sonar.server.platform.SettingsChangeNotifier;
import org.sonar.server.plugins.InstalledPluginReferentialFactory;
import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
import org.sonar.server.plugins.ServerPluginRepository;
import org.sonar.server.plugins.UpdateCenterMatrixFactory;
import org.sonar.server.rule.RuleRepositories;
@@ -149,15 +150,15 @@ public final class JRubyFacade {
}
public void uninstallPlugin(String pluginKey) {
- get(ServerPluginJarsInstaller.class).uninstall(pluginKey);
+ get(ServerPluginRepository.class).uninstall(pluginKey);
}
public void cancelPluginUninstalls() {
- get(ServerPluginJarsInstaller.class).cancelUninstalls();
+ get(ServerPluginRepository.class).cancelUninstalls();
}
public List getPluginUninstalls() {
- return get(ServerPluginJarsInstaller.class).getUninstalledPluginFilenames();
+ return get(ServerPluginRepository.class).getUninstalledPluginFilenames();
}
public UpdateCenter getUpdatePluginCenter(boolean forceReload) {
@@ -173,12 +174,11 @@ public final class JRubyFacade {
return get(PropertyDefinitions.class);
}
- public boolean hasPlugin(String key) {
- return get(PluginRepository.class).getPlugin(key) != null;
- }
-
- public Collection getPluginsMetadata() {
- return get(PluginRepository.class).getMetadata();
+ /**
+ * Used for WS api/updatecenter/installed_plugins, to be replaced by api/plugins/installed.
+ */
+ public Collection getPluginInfos() {
+ return get(PluginRepository.class).getPluginInfos();
}
public List> getWidgets(String resourceScope, String resourceQualifier, String resourceLanguage, Object[] availableMeasures) {
@@ -285,12 +285,13 @@ public final class JRubyFacade {
}
public Object getComponentByClassname(String pluginKey, String className) {
- Object component = null;
- Class> componentClass = get(ServerPluginRepository.class).getClass(pluginKey, className);
- if (componentClass != null) {
- component = get(componentClass);
+ Plugin plugin = get(PluginRepository.class).getPluginInstance(pluginKey);
+ try {
+ Class componentClass = plugin.getClass().getClassLoader().loadClass(className);
+ return get(componentClass);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(String.format("Class [%s] not found in plugin [%s]", className, pluginKey), e);
}
- return component;
}
private JRubyI18n getJRubyI18n() {
@@ -391,7 +392,7 @@ public final class JRubyFacade {
ComponentContainer container = Platform.getInstance().getContainer();
DatabaseMigration databaseMigration = container.getComponentByType(DatabaseMigration.class);
if (databaseMigration.status() == DatabaseMigration.Status.RUNNING
- || databaseMigration.status() == DatabaseMigration.Status.FAILED) {
+ || databaseMigration.status() == DatabaseMigration.Status.FAILED) {
return false;
}
if (databaseMigration.status() == DatabaseMigration.Status.SUCCEEDED) {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/debt/DebtModelPluginRepositoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/debt/DebtModelPluginRepositoryTest.java
index 942bb973c09..730584d829b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/debt/DebtModelPluginRepositoryTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/debt/DebtModelPluginRepositoryTest.java
@@ -28,8 +28,8 @@ import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.sonar.api.SonarPlugin;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
import java.io.FileInputStream;
import java.io.InputStream;
@@ -54,17 +54,15 @@ public class DebtModelPluginRepositoryTest {
@Test
public void test_component_initialization() throws Exception {
// we do have the "csharp-model.xml" file in src/test/resources
- PluginMetadata csharpPluginMetadata = mock(PluginMetadata.class);
- when(csharpPluginMetadata.getKey()).thenReturn("csharp");
+ PluginInfo csharpPluginMetadata = new PluginInfo("csharp");
// but we don' have the "php-model.xml" one
- PluginMetadata phpPluginMetadata = mock(PluginMetadata.class);
- when(phpPluginMetadata.getKey()).thenReturn("php");
+ PluginInfo phpPluginMetadata = new PluginInfo("php");
PluginRepository repository = mock(PluginRepository.class);
- when(repository.getMetadata()).thenReturn(Lists.newArrayList(csharpPluginMetadata, phpPluginMetadata));
+ when(repository.getPluginInfos()).thenReturn(Lists.newArrayList(csharpPluginMetadata, phpPluginMetadata));
FakePlugin fakePlugin = new FakePlugin();
- when(repository.getPlugin(anyString())).thenReturn(fakePlugin);
+ when(repository.getPluginInstance(anyString())).thenReturn(fakePlugin);
modelFinder = new DebtModelPluginRepository(repository, TEST_XML_PREFIX_PATH);
// when
diff --git a/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java b/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java
index 5c49de4aef1..e8df89bb003 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java
@@ -41,7 +41,7 @@ import org.elasticsearch.node.Node;
import org.elasticsearch.node.NodeBuilder;
import org.elasticsearch.search.SearchHit;
import org.junit.rules.ExternalResource;
-import org.sonar.api.platform.ComponentContainer;
+import org.sonar.core.platform.ComponentContainer;
import org.sonar.server.search.BaseDoc;
import org.sonar.test.TestUtils;
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerFileSystemTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerFileSystemTest.java
index c06a7887022..57bf62c771a 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerFileSystemTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerFileSystemTest.java
@@ -37,20 +37,6 @@ public class DefaultServerFileSystemTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- @Test
- public void find_plugins() throws Exception {
- List plugins = new DefaultServerFileSystem(
- new File(Resources.getResource(PATH + "shouldFindPlugins").toURI()), temp.newFolder(), null).getUserPlugins();
- assertThat(plugins).hasSize(2);
- }
-
- @Test
- public void not_fail_if_no_plugins() throws Exception {
- List plugins = new DefaultServerFileSystem(
- new File(Resources.getResource(PATH + "shouldNotFailIfNoPlugins").toURI()), temp.newFolder(), null).getUserPlugins();
- assertThat(plugins).isEmpty();
- }
-
@Test
public void find_checkstyle_extensions() throws Exception {
ServerFileSystem fs = new DefaultServerFileSystem(
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/RailsAppsDeployerTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/RailsAppsDeployerTest.java
index a64486ca9d9..d110225210d 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/RailsAppsDeployerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/RailsAppsDeployerTest.java
@@ -23,9 +23,9 @@ import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
import org.sonar.api.platform.ServerFileSystem;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
import java.io.File;
import java.net.URL;
@@ -77,7 +77,7 @@ public class RailsAppsDeployerTest {
when(fileSystem.getTempDir()).thenReturn(tempDir);
PluginRepository pluginRepository = mock(PluginRepository.class);
- when(pluginRepository.getMetadata()).thenReturn(Collections.emptyList());
+ when(pluginRepository.getPluginInfos()).thenReturn(Collections.emptyList());
new RailsAppsDeployer(fileSystem, pluginRepository).start();
File appDir = new File(tempDir, "ror");
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/SonarHomeTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/SonarHomeTest.java
deleted file mode 100644
index 66a4069fba1..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/SonarHomeTest.java
+++ /dev/null
@@ -1,29 +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.server.platform;
-
-import org.junit.Test;
-
-public class SonarHomeTest {
- @Test
- public void iDontKnowHowToSimplyTestThisClass() {
-
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java
index ef082c716b2..9e70d80a699 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java
@@ -21,22 +21,22 @@
package org.sonar.server.platform.monitoring;
import org.junit.Test;
-import org.sonar.api.Plugin;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
+import org.sonar.updatecenter.common.Version;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Arrays;
import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class PluginsMonitorTest {
- PluginsMonitor sut = new PluginsMonitor(new FakePluginRepository());;
+ PluginRepository repo = mock(PluginRepository.class);
+ PluginsMonitor sut = new PluginsMonitor(repo);
@Test
public void name() {
@@ -44,42 +44,28 @@ public class PluginsMonitorTest {
}
@Test
- public void plugin_name_and_version() {
+ public void plugin_name_and_version() throws Exception {
+ when(repo.getPluginInfos()).thenReturn(Arrays.asList(
+ new PluginInfo("key-1")
+ .setName("plugin-1")
+ .setVersion(Version.create("1.1")),
+ new PluginInfo("key-2")
+ .setName("plugin-2")
+ .setVersion(Version.create("2.2")),
+ new PluginInfo("no-version")
+ .setName("No Version")));
+
LinkedHashMap attributes = sut.attributes();
assertThat(attributes).containsKeys("key-1", "key-2");
assertThat((Map) attributes.get("key-1"))
.containsEntry("Name", "plugin-1")
.containsEntry("Version", "1.1");
- assertThat((Map)attributes.get("key-2"))
+ assertThat((Map) attributes.get("key-2"))
.containsEntry("Name", "plugin-2")
.containsEntry("Version", "2.2");
- }
-
- private static class FakePluginRepository implements PluginRepository {
-
- @Override
- public Plugin getPlugin(String key) {
- return null;
- }
-
- @Override
- public Collection getMetadata() {
- List plugins = new ArrayList<>();
- plugins.add(DefaultPluginMetadata
- .create("key-1")
- .setName("plugin-1")
- .setVersion("1.1"));
- plugins.add(DefaultPluginMetadata
- .create("key-2")
- .setName("plugin-2")
- .setVersion("2.2"));
- return plugins;
- }
-
- @Override
- public PluginMetadata getMetadata(String pluginKey) {
- return null;
- }
+ assertThat((Map) attributes.get("no-version"))
+ .containsEntry("Name", "No Version")
+ .doesNotContainKey("Version");
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/InstalledPluginReferentialFactoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/InstalledPluginReferentialFactoryTest.java
index 40e1ada4f35..58c0e12c449 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/plugins/InstalledPluginReferentialFactoryTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/InstalledPluginReferentialFactoryTest.java
@@ -20,9 +20,8 @@
package org.sonar.server.plugins;
import org.junit.Test;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
@@ -33,23 +32,22 @@ public class InstalledPluginReferentialFactoryTest {
@Test
public void should_create_plugin_referential() {
- PluginMetadata metadata = mock(DefaultPluginMetadata.class);
- when(metadata.getKey()).thenReturn("foo");
+ PluginInfo info = new PluginInfo("foo");
PluginRepository pluginRepository = mock(PluginRepository.class);
- when(pluginRepository.getMetadata()).thenReturn(newArrayList(metadata));
- InstalledPluginReferentialFactory installedPluginReferentialFactory = new InstalledPluginReferentialFactory(pluginRepository);
+ when(pluginRepository.getPluginInfos()).thenReturn(newArrayList(info));
+ InstalledPluginReferentialFactory factory = new InstalledPluginReferentialFactory(pluginRepository);
- assertThat(installedPluginReferentialFactory.getInstalledPluginReferential()).isNull();
- installedPluginReferentialFactory.start();
- assertThat(installedPluginReferentialFactory.getInstalledPluginReferential()).isNotNull();
- assertThat(installedPluginReferentialFactory.getInstalledPluginReferential().getPlugins()).hasSize(1);
+ assertThat(factory.getInstalledPluginReferential()).isNull();
+ factory.start();
+ assertThat(factory.getInstalledPluginReferential()).isNotNull();
+ assertThat(factory.getInstalledPluginReferential().getPlugins()).hasSize(1);
}
@Test(expected = RuntimeException.class)
public void should_encapsulate_exception() {
PluginRepository pluginRepository = mock(PluginRepository.class);
- when(pluginRepository.getMetadata()).thenThrow(new IllegalArgumentException());
- InstalledPluginReferentialFactory installedPluginReferentialFactory = new InstalledPluginReferentialFactory(pluginRepository);
- installedPluginReferentialFactory.start();
+ when(pluginRepository.getPluginInfos()).thenThrow(new IllegalArgumentException());
+ InstalledPluginReferentialFactory factory = new InstalledPluginReferentialFactory(pluginRepository);
+ factory.start();
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/MimeTypesTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/MimeTypesTest.java
index 6c5f4412026..25b5b4978c4 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/plugins/MimeTypesTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/MimeTypesTest.java
@@ -20,6 +20,7 @@
package org.sonar.server.plugins;
import org.junit.Test;
+import org.sonar.test.TestUtils;
import static org.assertj.core.api.Assertions.assertThat;
@@ -35,4 +36,9 @@ public class MimeTypesTest {
assertThat(MimeTypes.getByFilename("static/sqale/sqale.css")).isEqualTo("text/css");
assertThat(MimeTypes.getByFilename("sqale.css")).isEqualTo("text/css");
}
+
+ @Test
+ public void only_statics() throws Exception {
+ assertThat(TestUtils.hasOnlyPrivateConstructors(MimeTypes.class)).isTrue();
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java
index bf460fffd2b..a5178f40383 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java
@@ -29,11 +29,12 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.sonar.api.utils.HttpDownloader;
import org.sonar.api.utils.SonarException;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.core.platform.PluginInfo;
import org.sonar.server.platform.DefaultServerFileSystem;
import org.sonar.updatecenter.common.Plugin;
import org.sonar.updatecenter.common.Release;
import org.sonar.updatecenter.common.UpdateCenter;
+import org.sonar.updatecenter.common.Version;
import java.io.File;
import java.net.URI;
@@ -66,7 +67,6 @@ public class PluginDownloaderTest {
UpdateCenter updateCenter;
HttpDownloader httpDownloader;
PluginDownloader pluginDownloader;
- ServerPluginJarInstaller installer;
@Before
public void before() throws Exception {
@@ -88,8 +88,7 @@ public class PluginDownloaderTest {
downloadDir = testFolder.newFolder("downloads");
when(defaultServerFileSystem.getDownloadedPluginsDir()).thenReturn(downloadDir);
- installer = new ServerPluginJarInstaller();
- pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, defaultServerFileSystem, installer);
+ pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, defaultServerFileSystem);
}
@After
@@ -155,7 +154,7 @@ public class PluginDownloaderTest {
File downloadDir = testFolder.newFile();
when(defaultServerFileSystem.getDownloadedPluginsDir()).thenReturn(downloadDir);
- pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, defaultServerFileSystem, installer);
+ pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, defaultServerFileSystem);
try {
pluginDownloader.start();
fail();
@@ -220,26 +219,18 @@ public class PluginDownloaderTest {
pluginDownloader.start();
assertThat(pluginDownloader.getDownloadedPluginFilenames()).hasSize(0);
- copyFileToDirectory(new File(resource("foo-plugin-1.0.jar")), downloadDir);
+ copyFileToDirectory(TestProjectUtils.jarOf("test-base-plugin"), downloadDir);
assertThat(pluginDownloader.getDownloadedPlugins()).hasSize(1);
- DefaultPluginMetadata metadata = pluginDownloader.getDownloadedPlugins().iterator().next();
- assertThat(metadata.getKey()).isEqualTo("foo");
- assertThat(metadata.getName()).isEqualTo("Foo");
- assertThat(metadata.getVersion()).isEqualTo("1.0");
- assertThat(metadata.getOrganization()).isEqualTo("SonarSource");
- assertThat(metadata.getOrganizationUrl()).isEqualTo("http://www.sonarsource.org");
- assertThat(metadata.getLicense()).isEqualTo("LGPL 3");
- assertThat(metadata.getMainClass()).isEqualTo("foo.Main");
- }
-
- private URI resource(String fileName) throws URISyntaxException {
- URL resource = getClass().getResource(getClass().getSimpleName() + "/" + fileName);
- return resource.toURI();
+ PluginInfo info = pluginDownloader.getDownloadedPlugins().iterator().next();
+ assertThat(info.getKey()).isEqualTo("testbase");
+ assertThat(info.getName()).isEqualTo("Base Plugin");
+ assertThat(info.getVersion()).isEqualTo(Version.create("0.1-SNAPSHOT"));
+ assertThat(info.getMainClass()).isEqualTo("BasePlugin");
}
@Test
- public void getDownloadedPluginFilenames_reads_plugin_metadata_of_files_in_download_folder() throws Exception {
+ public void getDownloadedPluginFilenames_reads_plugin_info_of_files_in_download_folder() throws Exception {
pluginDownloader.start();
assertThat(pluginDownloader.getDownloadedPlugins()).hasSize(0);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginReferentialMetadataConverterTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginReferentialMetadataConverterTest.java
index a7cc85c9694..c7891203caa 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginReferentialMetadataConverterTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginReferentialMetadataConverterTest.java
@@ -20,23 +20,19 @@
package org.sonar.server.plugins;
import org.junit.Test;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.core.platform.PluginInfo;
import org.sonar.updatecenter.common.PluginReferential;
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
public class PluginReferentialMetadataConverterTest {
@Test
- public void should_convert_metadata_to_plugin_referential() {
- PluginMetadata metadata = mock(DefaultPluginMetadata.class);
- when(metadata.getKey()).thenReturn("foo");
+ public void should_convert_info_to_plugin_referential() {
+ PluginInfo info = new PluginInfo("foo");
- PluginReferential pluginReferential = PluginReferentialMetadataConverter.getInstalledPluginReferential(newArrayList(metadata));
+ PluginReferential pluginReferential = PluginReferentialMetadataConverter.getInstalledPluginReferential(newArrayList(info));
assertThat(pluginReferential).isNotNull();
assertThat(pluginReferential.getPlugins()).hasSize(1);
assertThat(pluginReferential.getPlugins().get(0).getKey()).isEqualTo("foo");
@@ -44,11 +40,9 @@ public class PluginReferentialMetadataConverterTest {
@Test
public void should_not_add_core_plugin() {
- PluginMetadata metadata = mock(DefaultPluginMetadata.class);
- when(metadata.getKey()).thenReturn("foo");
- when(metadata.isCore()).thenReturn(true);
+ PluginInfo info = new PluginInfo("foo").setCore(true);
- PluginReferential pluginReferential = PluginReferentialMetadataConverter.getInstalledPluginReferential(newArrayList(metadata));
+ PluginReferential pluginReferential = PluginReferentialMetadataConverter.getInstalledPluginReferential(newArrayList(info));
assertThat(pluginReferential).isNotNull();
assertThat(pluginReferential.getPlugins()).hasSize(0);
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginJarsInstallerTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginJarsInstallerTest.java
deleted file mode 100644
index 8edde701e28..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginJarsInstallerTest.java
+++ /dev/null
@@ -1,309 +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.server.plugins;
-
-import com.google.common.io.Resources;
-import org.apache.commons.io.FileUtils;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.Server;
-import org.sonar.api.platform.ServerUpgradeStatus;
-import org.sonar.api.utils.MessageException;
-import org.sonar.core.plugins.DefaultPluginMetadata;
-import org.sonar.server.platform.DefaultServerFileSystem;
-
-import java.io.File;
-import java.util.Collection;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class ServerPluginJarsInstallerTest {
-
- @Rule
- public ExpectedException exception = ExpectedException.none();
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- DefaultServerFileSystem fileSystem;
- File homeDir, pluginsDir, downloadsDir, bundledDir, trashDir, coreDir;
- ServerPluginJarInstaller jarInstaller;
- ServerPluginJarsInstaller jarsInstaller;
- Server server = mock(Server.class);
- ServerUpgradeStatus upgradeStatus = mock(ServerUpgradeStatus.class);
-
- @Before
- public void before() throws Exception {
- when(server.getVersion()).thenReturn("3.1");
- when(server.getDeployDir()).thenReturn(temp.newFolder("deploy"));
-
- homeDir = temp.newFolder("home");
- pluginsDir = new File(homeDir, "extensions/plugins");
- FileUtils.forceMkdir(pluginsDir);
- downloadsDir = new File(homeDir, "extensions/downloads");
- trashDir = new File(homeDir, "extensions/trash");
- bundledDir = new File(homeDir, "lib/bundled-plugins");
- coreDir = new File(homeDir, "lib/core-plugins");
- FileUtils.forceMkdir(bundledDir);
-
- fileSystem = new DefaultServerFileSystem(homeDir, temp.newFolder(), server);
- jarInstaller = new ServerPluginJarInstaller();
- jarsInstaller = new ServerPluginJarsInstaller(server, upgradeStatus, fileSystem, jarInstaller);
- }
-
- private File jar(String name) throws Exception {
- return new File(Resources.getResource(getClass(), "ServerPluginJarsInstallerTest/" + name).toURI());
- }
-
- @Test
- public void copy_bundled_plugin_on_fresh_install() throws Exception {
- when(upgradeStatus.isFreshInstall()).thenReturn(true);
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), bundledDir);
-
- jarsInstaller.install();
-
- assertThat(FileUtils.listFiles(pluginsDir, new String[] {"jar"}, false)).hasSize(1);
- assertThat(new File(pluginsDir, "foo-plugin-1.0.jar")).exists().isFile();
- PluginMetadata plugin = jarsInstaller.getMetadata("foo");
- assertThat(plugin.getName()).isEqualTo("Foo");
- assertThat(plugin.getDeployedFiles()).hasSize(1);
- assertThat(plugin.isCore()).isFalse();
- assertThat(plugin.isUseChildFirstClassLoader()).isFalse();
- }
-
- @Test
- public void do_not_copy_bundled_plugin_on_non_fresh_install() throws Exception {
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), bundledDir);
-
- jarsInstaller.install();
-
- assertThat(FileUtils.listFiles(pluginsDir, new String[]{"jar"}, false)).isEmpty();
- }
-
- @Test
- public void do_not_copy_bundled_plugin_if_already_installed() throws Exception {
- // fresh install but plugins are already packaged in extensions/plugins
- when(upgradeStatus.isFreshInstall()).thenReturn(true);
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), bundledDir);
- FileUtils.copyFileToDirectory(jar("foo-plugin-2.0.jar"), pluginsDir);
- FileUtils.copyFileToDirectory(jar("bar-plugin-1.0.jar"), pluginsDir);
-
- jarsInstaller.install();
-
- // do not copy foo 1.0
- assertThat(FileUtils.listFiles(pluginsDir, new String[]{"jar"}, false)).hasSize(2);
- assertThat(new File(pluginsDir, "foo-plugin-2.0.jar")).exists().isFile();
- assertThat(new File(pluginsDir, "bar-plugin-1.0.jar")).exists().isFile();
- PluginMetadata plugin = jarsInstaller.getMetadata("foo");
- assertThat(plugin.getVersion()).isEqualTo("2.0");
- }
-
- @Test
- public void deploy_installed_plugin() throws Exception {
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), pluginsDir);
-
- jarsInstaller.install();
-
- // check that the plugin is registered
- assertThat(jarsInstaller.getMetadata()).hasSize(1);
- PluginMetadata plugin = jarsInstaller.getMetadata("foo");
- assertThat(plugin.getName()).isEqualTo("Foo");
- assertThat(plugin.getDeployedFiles()).hasSize(1);
- assertThat(plugin.isCore()).isFalse();
- assertThat(plugin.isUseChildFirstClassLoader()).isFalse();
-
- // check that the file is still present in extensions/plugins
- assertThat(FileUtils.listFiles(pluginsDir, new String[]{"jar"}, false)).hasSize(1);
- assertThat(new File(pluginsDir, "foo-plugin-1.0.jar")).exists().isFile();
- }
-
- @Test
- public void ignore_non_plugin_jars() throws Exception {
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
- FileUtils.copyFileToDirectory(jar("not-a-plugin.jar"), pluginsDir);
-
- jarsInstaller.install();
-
- // nothing to install but keep the file
- assertThat(jarsInstaller.getMetadata()).isEmpty();
- assertThat(FileUtils.listFiles(pluginsDir, new String[] {"jar"}, false)).hasSize(1);
- assertThat(new File(pluginsDir, "not-a-plugin.jar")).exists().isFile();
- }
-
- @Test
- public void fail_if_plugin_requires_greater_SQ_version() throws Exception {
- exception.expect(MessageException.class);
- exception.expectMessage("Plugin switchoffviolations needs a more recent version of SonarQube than 2.0. At least 2.5 is expected");
-
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
- when(server.getVersion()).thenReturn("2.0");
- FileUtils.copyFileToDirectory(jar("require-sq-2.5.jar"), pluginsDir);
-
- jarsInstaller.install();
- }
-
- @Test
- public void move_downloaded_plugins() throws Exception {
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), downloadsDir);
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
-
- jarsInstaller.install();
-
- assertThat(FileUtils.listFiles(pluginsDir, new String[]{"jar"}, false)).hasSize(1);
- assertThat(FileUtils.listFiles(downloadsDir, new String[] {"jar"}, false)).isEmpty();
- assertThat(new File(pluginsDir, "foo-plugin-1.0.jar")).exists().isFile();
- }
-
- @Test
- public void downloaded_plugins_overrides_existing_plugin() throws Exception {
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), pluginsDir);
- FileUtils.copyFileToDirectory(jar("foo-plugin-2.0.jar"), downloadsDir);
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
-
- jarsInstaller.install();
-
- assertThat(FileUtils.listFiles(pluginsDir, new String[] {"jar"}, false)).hasSize(1);
- assertThat(FileUtils.listFiles(downloadsDir, new String[] {"jar"}, false)).isEmpty();
- assertThat(new File(pluginsDir, "foo-plugin-2.0.jar")).exists().isFile();
- }
-
- @Test
- public void downloaded_plugins_overrides_existing_plugin_even_if_same_filename() throws Exception {
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), pluginsDir, true);
- // foo-plugin-1.0.jar in extensions/downloads is in fact version 2.0. It's used to verify
- // that it has correctly overridden extensions/plugins/foo-plugin-1.0.jar
- FileUtils.copyFile(jar("foo-plugin-2.0.jar"), new File(downloadsDir, "foo-plugin-1.0.jar"));
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
-
- jarsInstaller.install();
-
- PluginMetadata plugin = jarsInstaller.getMetadata("foo");
- assertThat(plugin).isNotNull();
- assertThat(plugin.getVersion()).isEqualTo("2.0");
- assertThat(FileUtils.listFiles(pluginsDir, new String[] {"jar"}, false)).hasSize(1);
- assertThat(FileUtils.listFiles(downloadsDir, new String[] {"jar"}, false)).isEmpty();
- File installed = new File(pluginsDir, "foo-plugin-1.0.jar");
- assertThat(installed).exists().isFile();
- }
-
- @Test
- public void delete_trash() throws Exception {
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), trashDir);
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
-
- jarsInstaller.install();
-
- assertThat(FileUtils.listFiles(pluginsDir, new String[] {"jar"}, false)).isEmpty();
- assertThat(trashDir).doesNotExist();
- }
-
- @Test
- public void fail_if_two_installed_plugins_with_same_key() throws Exception {
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), pluginsDir);
- FileUtils.copyFileToDirectory(jar("foo-plugin-2.0.jar"), pluginsDir);
-
- try {
- jarsInstaller.install();
- fail();
- } catch (MessageException e) {
- assertThat(e.getMessage())
- .contains("Found two files for the same plugin 'foo'")
- .contains("foo-plugin-1.0.jar")
- .contains("foo-plugin-2.0.jar");
- }
- }
-
- @Test
- public void uninstall_plugin() throws Exception {
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), pluginsDir);
-
- jarsInstaller.install();
- jarsInstaller.uninstall("foo");
-
- assertThat(FileUtils.listFiles(pluginsDir, new String[]{"jar"}, false)).isEmpty();
- assertThat(FileUtils.listFiles(trashDir, new String[] {"jar"}, false)).hasSize(1);
- assertThat(jarsInstaller.getUninstalledPluginFilenames()).containsOnly("foo-plugin-1.0.jar");
- }
-
- @Test
- public void pending_removals_reads_metadata() throws Exception {
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), pluginsDir);
-
- jarsInstaller.install();
- jarsInstaller.uninstall("foo");
-
- assertThat(FileUtils.listFiles(pluginsDir, new String[] {"jar"}, false)).isEmpty();
- assertThat(FileUtils.listFiles(trashDir, new String[] {"jar"}, false)).hasSize(1);
- Collection removals = jarsInstaller.getUninstalledPlugins();
- assertThat(removals).hasSize(1);
- PluginMetadata metadata = removals.iterator().next();
- assertThat(metadata.getKey()).isEqualTo("foo");
- assertThat(metadata.getName()).isEqualTo("Foo");
- assertThat(metadata.getVersion()).isEqualTo("1.0");
- assertThat(metadata.getOrganization()).isEqualTo("SonarSource");
- assertThat(metadata.getOrganizationUrl()).isEqualTo("http://www.sonarsource.org");
- assertThat(metadata.getLicense()).isEqualTo("LGPL 3");
- assertThat(metadata.getMainClass()).isEqualTo("foo.Main");
- }
-
- @Test
- public void cancel_uninstallation() throws Exception {
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), pluginsDir);
-
- jarsInstaller.install();
- jarsInstaller.uninstall("foo");
- jarsInstaller.cancelUninstalls();
-
- assertThat(FileUtils.listFiles(pluginsDir, new String[] {"jar"}, false)).hasSize(1);
- assertThat(FileUtils.listFiles(trashDir, new String[] {"jar"}, false)).hasSize(0);
- assertThat(jarsInstaller.getUninstalledPluginFilenames()).isEmpty();
- }
-
- @Test
- public void deploy_core_plugins() throws Exception {
- when(upgradeStatus.isFreshInstall()).thenReturn(false);
- FileUtils.copyFileToDirectory(jar("foo-plugin-1.0.jar"), coreDir);
-
- jarsInstaller.install();
-
- // do not deploy in extensions/plugins
- assertThat(FileUtils.listFiles(pluginsDir, new String[] {"jar"}, false)).hasSize(0);
-
- // do not remove from lib/core-plugins
- assertThat(FileUtils.listFiles(coreDir, new String[] {"jar"}, false)).hasSize(1);
-
- PluginMetadata plugin = jarsInstaller.getMetadata("foo");
- assertThat(plugin).isNotNull();
- assertThat(plugin.isCore()).isTrue();
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java
index 5f1898dae31..ea87cb3af88 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java
@@ -19,47 +19,298 @@
*/
package org.sonar.server.plugins;
-import com.google.common.io.Resources;
+import com.google.common.collect.ImmutableSet;
+import org.apache.commons.io.FileUtils;
import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
+import org.sonar.api.platform.Server;
+import org.sonar.api.platform.ServerUpgradeStatus;
+import org.sonar.api.utils.MessageException;
+import org.sonar.core.platform.PluginLoader;
+import org.sonar.server.platform.DefaultServerFileSystem;
+import org.sonar.updatecenter.common.Version;
import java.io.File;
-import java.util.Arrays;
+import java.io.IOException;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ServerPluginRepositoryTest {
- ServerPluginRepository repository;
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ Server server = mock(Server.class);
+ ServerUpgradeStatus upgradeStatus = mock(ServerUpgradeStatus.class);
+ DefaultServerFileSystem fs = mock(DefaultServerFileSystem.class, Mockito.RETURNS_DEEP_STUBS);
+ PluginLoader pluginLoader = new PluginLoader(new ServerPluginUnzipper(fs));
+ ServerPluginRepository underTest = new ServerPluginRepository(server, upgradeStatus, fs, pluginLoader);
+
+ @Before
+ public void setUp() throws IOException {
+ when(fs.getBundledPluginsDir()).thenReturn(temp.newFolder());
+ when(fs.getCorePluginsDir()).thenReturn(temp.newFolder());
+ when(fs.getDeployedPluginsDir()).thenReturn(temp.newFolder());
+ when(fs.getDownloadedPluginsDir()).thenReturn(temp.newFolder());
+ when(fs.getHomeDir()).thenReturn(temp.newFolder());
+ when(fs.getInstalledPluginsDir()).thenReturn(temp.newFolder());
+ when(fs.getTempDir()).thenReturn(temp.newFolder());
+ when(server.getVersion()).thenReturn("5.2");
+ }
@After
- public void stop() {
- if (repository != null) {
- repository.stop();
+ public void tearDown() throws Exception {
+ underTest.stop();
+ }
+
+ /**
+ * The first server startup (fresh db) installs bundled plugins and instantiates bundled + core plugins.
+ */
+ @Test
+ public void first_startup_installs_bundled_plugins() throws Exception {
+ copyTestPluginTo("test-base-plugin", fs.getBundledPluginsDir());
+ copyTestPluginTo("test-core-plugin", fs.getCorePluginsDir());
+ when(upgradeStatus.isFreshInstall()).thenReturn(true);
+
+ underTest.start();
+
+ // both plugins are installed
+ assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("core", "testbase");
+ assertThat(underTest.getPluginInstance("core").getClass().getName()).isEqualTo("CorePlugin");
+ assertThat(underTest.getPluginInstance("testbase").getClass().getName()).isEqualTo("BasePlugin");
+ assertThat(underTest.hasPlugin("testbase")).isTrue();
+ }
+
+ @Test
+ public void bundled_plugins_are_not_installed_if_not_fresh_server() throws Exception {
+ copyTestPluginTo("test-base-plugin", fs.getBundledPluginsDir());
+ when(upgradeStatus.isFreshInstall()).thenReturn(false);
+
+ underTest.start();
+
+ assertThat(underTest.getPluginInfos()).isEmpty();
+ }
+
+ @Test
+ public void standard_startup_loads_core_and_installed_plugins() throws Exception {
+ copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("test-core-plugin", fs.getCorePluginsDir());
+
+ underTest.start();
+
+ // both plugins are installed
+ assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("core", "testbase");
+ assertThat(underTest.getPluginInstance("core").getClass().getName()).isEqualTo("CorePlugin");
+ assertThat(underTest.getPluginInstance("testbase").getClass().getName()).isEqualTo("BasePlugin");
+ }
+
+ /**
+ * That sounds impossible, there are still core plugins for now, but it's still valuable
+ * to test sensibility to null values.
+ */
+ @Test
+ public void no_plugins_at_all_on_startup() throws Exception {
+ underTest.start();
+
+ assertThat(underTest.getPluginInfos()).isEmpty();
+ assertThat(underTest.getPluginInfosByKeys()).isEmpty();
+ assertThat(underTest.getUninstalledPlugins()).isEmpty();
+ assertThat(underTest.hasPlugin("testbase")).isFalse();
+ }
+
+ @Test
+ public void fail_if_multiple_jars_for_same_installed_plugin_on_startup() throws Exception {
+ copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("test-base-plugin-v2", fs.getInstalledPluginsDir());
+
+ try {
+ underTest.start();
+ fail();
+ } catch (MessageException e) {
+ assertThat(e)
+ .hasMessageStartingWith("Found two files for the same plugin [testbase]: ")
+ // order is not guaranteed, so assertion is split
+ .hasMessageContaining("test-base-plugin-0.1-SNAPSHOT.jar")
+ .hasMessageContaining("test-base-plugin-0.2-SNAPSHOT.jar");
}
}
@Test
- public void testStart() throws Exception {
- ServerPluginJarsInstaller deployer = mock(ServerPluginJarsInstaller.class);
- File pluginFile = new File(Resources.getResource("org/sonar/server/plugins/ServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar").toURI());
- PluginMetadata plugin = DefaultPluginMetadata.create(pluginFile)
- .setKey("artifactsize")
- .setMainClass("org.sonar.plugins.artifactsize.ArtifactSizePlugin")
- .addDeployedFile(pluginFile);
- when(deployer.getMetadata()).thenReturn(Arrays.asList(plugin));
+ public void install_downloaded_plugins_on_startup() throws Exception {
+ File downloadedJar = copyTestPluginTo("test-base-plugin", fs.getDownloadedPluginsDir());
+
+ underTest.start();
+
+ // plugin is moved to extensions/plugins then loaded
+ assertThat(downloadedJar).doesNotExist();
+ assertThat(new File(fs.getInstalledPluginsDir(), downloadedJar.getName())).isFile().exists();
+ assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase");
+ assertThat(underTest.getPluginInstance("testbase").getClass().getName()).isEqualTo("BasePlugin");
+ }
+
+ @Test
+ public void downloaded_file_overrides_existing_installed_file_on_startup() throws Exception {
+ File installedV1 = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ File downloadedV2 = copyTestPluginTo("test-base-plugin-v2", fs.getDownloadedPluginsDir());
+
+ underTest.start();
+
+ // plugin is moved to extensions/plugins and replaces v1
+ assertThat(downloadedV2).doesNotExist();
+ assertThat(installedV1).doesNotExist();
+ assertThat(new File(fs.getInstalledPluginsDir(), downloadedV2.getName())).exists();
+ assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase");
+ assertThat(underTest.getPluginInfo("testbase").getVersion()).isEqualTo(Version.create("0.2-SNAPSHOT"));
+ }
+
+ @Test
+ public void blacklisted_plugin_is_automatically_uninstalled_on_startup() throws Exception {
+ underTest.setBlacklistedPluginKeys(ImmutableSet.of("testbase", "issuesreport"));
+ File jar = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+
+ underTest.start();
- repository = new ServerPluginRepository(deployer);
- repository.start();
+ // plugin is not installed and file is deleted
+ assertThat(underTest.getPluginInfos()).isEmpty();
+ assertThat(jar).doesNotExist();
+ }
+
+ @Test
+ public void test_plugin_requirements_at_startup() throws Exception {
+ copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir());
+
+ underTest.start();
+
+ // both plugins are installed
+ assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase", "testrequire");
+ }
+
+ @Test
+ public void plugin_is_ignored_if_required_plugin_is_missing_at_startup() throws Exception {
+ copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir());
+
+ underTest.start();
+
+ // plugin is not installed as test-base-plugin is missing
+ assertThat(underTest.getPluginInfosByKeys()).isEmpty();
+ }
+
+ @Test
+ public void plugin_is_ignored_if_required_plugin_is_too_old_at_startup() throws Exception {
+ copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("test-requirenew-plugin", fs.getInstalledPluginsDir());
+
+ underTest.start();
+
+ // the plugin "requirenew" is not installed as it requires base 0.2+ to be installed.
+ assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase");
+ }
+
+ @Test
+ public void plugin_is_ignored_at_startup_if_unsupported_sq() throws Exception {
+ when(server.getVersion()).thenReturn("1.0");
+ copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+
+ underTest.start();
+
+ // plugin requires SQ 4.5.1 but SQ 1.0 is installed
+ assertThat(underTest.getPluginInfos()).isEmpty();
+ }
+
+ @Test
+ public void uninstall() throws Exception {
+ File installedJar = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+
+ underTest.start();
+ assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase");
+ underTest.uninstall("testbase");
+
+ assertThat(installedJar).doesNotExist();
+ // still up. Will be dropped after next startup
+ assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase");
+ assertThat(underTest.getUninstalledPluginFilenames()).containsOnly(installedJar.getName());
+ assertThat(underTest.getUninstalledPlugins()).extracting("key").containsOnly("testbase");
+ }
+
+ @Test
+ public void uninstall_dependents() throws Exception {
+ File base = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir());
+
+ underTest.start();
+ assertThat(underTest.getPluginInfos()).hasSize(2);
+ underTest.uninstall("testbase");
+
+ assertThat(base).doesNotExist();
+ assertThat(extension).doesNotExist();
+ assertThat(underTest.getUninstalledPluginFilenames()).containsOnly(base.getName(), extension.getName());
+ assertThat(underTest.getUninstalledPlugins()).extracting("key").containsOnly("testbase", "testrequire");
+ }
+
+ @Test
+ public void cancel_uninstall() throws Exception {
+ File base = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ underTest.start();
+
+ underTest.uninstall("testbase");
+ assertThat(base).doesNotExist();
+
+ underTest.cancelUninstalls();
+ assertThat(base).exists();
+ assertThat(underTest.getUninstalledPluginFilenames()).isEmpty();
+ assertThat(underTest.getUninstalledPlugins()).isEmpty();
+ }
+
+ @Test
+ public void install_plugin_and_its_extension_plugins_at_startup() throws Exception {
+ copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("test-extend-plugin", fs.getInstalledPluginsDir());
+
+ underTest.start();
+
+ // both plugins are installed
+ assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase", "testextend");
+ }
+
+ @Test
+ public void extension_plugin_is_ignored_if_base_plugin_is_missing_at_startup() throws Exception {
+ copyTestPluginTo("test-extend-plugin", fs.getInstalledPluginsDir());
+
+ underTest.start();
+
+ // plugin is not installed as its base plugin is not installed
+ assertThat(underTest.getPluginInfos()).isEmpty();
+ }
+
+ @Test
+ public void fail_is_missing_required_plugin() throws Exception {
+ try {
+ underTest.getPluginInfo("unknown");
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Plugin [unknown] does not exist");
+ }
+
+ try {
+ underTest.getPluginInstance("unknown");
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage("Plugin [unknown] does not exist");
+ }
+ }
- assertThat(repository.getPlugin("artifactsize")).isNotNull();
- assertThat(repository.getClassLoader("artifactsize")).isNotNull();
- assertThat(repository.getClass("artifactsize", "org.sonar.plugins.artifactsize.ArtifactSizeMetrics")).isNotNull();
- assertThat(repository.getClass("artifactsize", "org.Unknown")).isNull();
- assertThat(repository.getClass("other", "org.sonar.plugins.artifactsize.ArtifactSizeMetrics")).isNull();
+ private File copyTestPluginTo(String testPluginName, File toDir) throws IOException {
+ File jar = TestProjectUtils.jarOf(testPluginName);
+ // file is copied because it's supposed to be moved by the test
+ FileUtils.copyFileToDirectory(jar, toDir);
+ return new File(toDir, jar.getName());
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginUnzipperTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginUnzipperTest.java
new file mode 100644
index 00000000000..efea25d39e8
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginUnzipperTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.server.plugins;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.UnzippedPlugin;
+import org.sonar.server.platform.DefaultServerFileSystem;
+
+import java.io.File;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ServerPluginUnzipperTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ DefaultServerFileSystem fs = mock(DefaultServerFileSystem.class);
+ ServerPluginUnzipper underTest = new ServerPluginUnzipper(fs);
+
+ @Test
+ public void copy_all_classloader_files_to_dedicated_directory() throws Exception {
+ File deployDir = temp.newFolder();
+ when(fs.getDeployedPluginsDir()).thenReturn(deployDir);
+ File jar = TestProjectUtils.jarOf("test-libs-plugin");
+ PluginInfo info = PluginInfo.create(jar);
+
+ UnzippedPlugin unzipped = underTest.unzip(info);
+
+ // all the files loaded by classloaders (JAR + META-INF/libs/*.jar) are copied to the dedicated directory
+ // web/deploy/{pluginKey}
+ File pluginDeployDir = new File(deployDir, "testlibs");
+
+ assertThat(unzipped.getKey()).isEqualTo("testlibs");
+ assertThat(unzipped.getMain()).isFile().exists().hasParent(pluginDeployDir);
+ assertThat(unzipped.getLibs()).extracting("name").containsOnly("commons-daemon-1.0.15.jar", "commons-email-20030310.165926.jar");
+ for (File lib : unzipped.getLibs()) {
+ assertThat(lib).exists().isFile();
+ assertThat(lib.getCanonicalPath()).startsWith(pluginDeployDir.getCanonicalPath());
+ }
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/TestProjectUtils.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/TestProjectUtils.java
new file mode 100644
index 00000000000..00d579118ee
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/TestProjectUtils.java
@@ -0,0 +1,40 @@
+/*
+ * 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.server.plugins;
+
+import org.apache.commons.io.FileUtils;
+
+import java.io.File;
+import java.util.Collection;
+
+public class TestProjectUtils {
+
+ /**
+ * Get the artifact of plugins stored in src/test/projects
+ */
+ public static File jarOf(String dirName) {
+ File target = FileUtils.toFile(TestProjectUtils.class.getResource(String.format("/%s/target/", dirName)));
+ Collection jars = FileUtils.listFiles(target, new String[] {"jar"}, false);
+ if (jars == null || jars.size() != 1) {
+ throw new IllegalArgumentException("Test project is badly defined: " + dirName);
+ }
+ return jars.iterator().next();
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/CancelAllPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/CancelAllPluginsWsActionTest.java
index 4ff9f43f340..3d2260eba4f 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/CancelAllPluginsWsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/CancelAllPluginsWsActionTest.java
@@ -28,7 +28,7 @@ import org.sonar.api.server.ws.WebService;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
+import org.sonar.server.plugins.ServerPluginRepository;
import org.sonar.server.user.MockUserSession;
import org.sonar.server.ws.WsTester;
@@ -41,8 +41,8 @@ public class CancelAllPluginsWsActionTest {
private static final String DUMMY_CONTROLLER_KEY = "dummy";
private PluginDownloader pluginDownloader = mock(PluginDownloader.class);
- private ServerPluginJarsInstaller pluginJarsInstaller = mock(ServerPluginJarsInstaller.class);
- private CancelAllPluginsWsAction underTest = new CancelAllPluginsWsAction(pluginDownloader, pluginJarsInstaller);
+ private ServerPluginRepository pluginRepository = mock(ServerPluginRepository.class);
+ private CancelAllPluginsWsAction underTest = new CancelAllPluginsWsAction(pluginDownloader, pluginRepository);
private Request request = mock(Request.class);
private WsTester.TestResponse response = new WsTester.TestResponse();
@@ -90,7 +90,7 @@ public class CancelAllPluginsWsActionTest {
underTest.handle(request, response);
verify(pluginDownloader, times(1)).cancelDownloads();
- verify(pluginJarsInstaller, times(1)).cancelUninstalls();
+ verify(pluginRepository, times(1)).cancelUninstalls();
assertThat(response.outputAsString()).isEmpty();
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java
index 3780d88af00..11a544e1d23 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java
@@ -19,17 +19,17 @@
*/
package org.sonar.server.plugins.ws;
-import java.io.File;
import org.junit.Test;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.WebService;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.server.plugins.ServerPluginRepository;
import org.sonar.server.ws.WsTester;
+import org.sonar.updatecenter.common.Version;
+
+import java.io.File;
import static com.google.common.collect.ImmutableList.of;
-import static java.lang.String.valueOf;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -42,12 +42,12 @@ public class InstalledPluginsWsActionTest {
" \"plugins\":" + "[]" +
"}";
- private PluginRepository pluginRepository = mock(PluginRepository.class);
+ private ServerPluginRepository pluginRepository = mock(ServerPluginRepository.class);
private InstalledPluginsWsAction underTest = new InstalledPluginsWsAction(pluginRepository, new PluginWSCommons());
private Request request = mock(Request.class);
private WsTester.TestResponse response = new WsTester.TestResponse();
- private PluginMetadata corePlugin = corePlugin("core1", 10);
+ private PluginInfo corePlugin = corePlugin("core1", "1.0");
@Test
public void action_installed_is_defined() {
@@ -75,7 +75,7 @@ public class InstalledPluginsWsActionTest {
@Test
public void core_plugin_are_not_returned() throws Exception {
- when(pluginRepository.getMetadata()).thenReturn(of(corePlugin));
+ when(pluginRepository.getPluginInfos()).thenReturn(of(corePlugin));
underTest.handle(request, response);
@@ -84,9 +84,9 @@ public class InstalledPluginsWsActionTest {
@Test
public void empty_fields_are_not_serialized_to_json() throws Exception {
- when(pluginRepository.getMetadata()).thenReturn(
+ when(pluginRepository.getPluginInfos()).thenReturn(
of(
- (PluginMetadata) DefaultPluginMetadata.create("").setName("").setCore(false)
+ new PluginInfo("").setName("").setCore(false)
)
);
@@ -98,14 +98,14 @@ public class InstalledPluginsWsActionTest {
@Test
public void verify_properties_displayed_in_json_per_plugin() throws Exception {
String jarFilename = getClass().getSimpleName() + "/" + "some.jar";
- when(pluginRepository.getMetadata()).thenReturn(of(
- (PluginMetadata) DefaultPluginMetadata.create("plugKey").setName("plugName").setCore(false)
+ when(pluginRepository.getPluginInfos()).thenReturn(of(
+ new PluginInfo("plugKey").setName("plugName").setCore(false)
.setDescription("desc_it")
- .setVersion(valueOf(10))
+ .setVersion(Version.create("1.0"))
.setLicense("license_hey")
- .setOrganization("org_name")
+ .setOrganizationName("org_name")
.setOrganizationUrl("org_url")
- .setHomepage("homepage_url")
+ .setHomepageUrl("homepage_url")
.setIssueTrackerUrl("issueTracker_url")
.setFile(new File(getClass().getResource(jarFilename).toURI()))
.setImplementationBuild("sou_rev_sha1")
@@ -122,7 +122,7 @@ public class InstalledPluginsWsActionTest {
" \"key\": \"plugKey\"," +
" \"name\": \"plugName\"," +
" \"description\": \"desc_it\"," +
- " \"version\": \"10\"," +
+ " \"version\": \"1.0\"," +
" \"license\": \"license_hey\"," +
" \"organizationName\": \"org_name\"," +
" \"organizationUrl\": \"org_url\"," +
@@ -137,7 +137,7 @@ public class InstalledPluginsWsActionTest {
@Test
public void plugins_are_sorted_by_name_then_key_and_only_one_plugin_can_have_a_specific_name() throws Exception {
- when(pluginRepository.getMetadata()).thenReturn(
+ when(pluginRepository.getPluginInfos()).thenReturn(
of(
plugin("A", "name2"),
plugin("B", "name1"),
@@ -163,7 +163,7 @@ public class InstalledPluginsWsActionTest {
@Test
public void only_one_plugin_can_have_a_specific_name_and_key() throws Exception {
- when(pluginRepository.getMetadata()).thenReturn(
+ when(pluginRepository.getPluginInfos()).thenReturn(
of(
plugin("A", "name2"),
plugin("A", "name2")
@@ -183,15 +183,15 @@ public class InstalledPluginsWsActionTest {
assertThat(response.outputAsString()).containsOnlyOnce("name2");
}
- private static PluginMetadata corePlugin(String key, int version) {
- return DefaultPluginMetadata.create(key).setName(key).setCore(true).setVersion(valueOf(version));
+ private static PluginInfo corePlugin(String key, String version) {
+ return new PluginInfo(key).setName(key).setCore(true).setVersion(Version.create(version));
}
- private static PluginMetadata plugin(String key, String name, int version) {
- return DefaultPluginMetadata.create(key).setName(name).setCore(false).setVersion(valueOf(version));
+ private static PluginInfo plugin(String key, String name, String version) {
+ return new PluginInfo(key).setName(name).setCore(false).setVersion(Version.create(version));
}
- private static PluginMetadata plugin(String key, String name) {
- return DefaultPluginMetadata.create(key).setName(name).setCore(false).setVersion("1.0");
+ private static PluginInfo plugin(String key, String name) {
+ return new PluginInfo(key).setName(name).setCore(false).setVersion(Version.create("1.0"));
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java
index 558ed57839a..1849151312a 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java
@@ -23,39 +23,39 @@ import java.io.File;
import org.junit.Test;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.WebService;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.core.platform.PluginInfo;
import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
+import org.sonar.server.plugins.ServerPluginRepository;
import org.sonar.server.ws.WsTester;
+import org.sonar.updatecenter.common.Version;
import static com.google.common.collect.ImmutableList.of;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-import static org.sonar.core.plugins.DefaultPluginMetadata.create;
import static org.sonar.test.JsonAssert.assertJson;
public class PendingPluginsWsActionTest {
- public static final DefaultPluginMetadata GIT_PLUGIN_METADATA = create("scmgit")
+ public static final PluginInfo GIT_PLUGIN_INFO = new PluginInfo("scmgit")
.setName("Git")
.setDescription("Git SCM Provider.")
- .setVersion("1.0")
+ .setVersion(Version.create("1.0"))
.setLicense("GNU LGPL 3")
- .setOrganization("SonarSource")
+ .setOrganizationName("SonarSource")
.setOrganizationUrl("http://www.sonarsource.com")
- .setHomepage("http://redirect.sonarsource.com/plugins/scmgit.html")
+ .setHomepageUrl("http://redirect.sonarsource.com/plugins/scmgit.html")
.setIssueTrackerUrl("http://jira.codehaus.org/browse/SONARSCGIT")
.setFile(new File("/home/user/sonar-scm-git-plugin-1.0.jar"))
.setImplementationBuild("9ce9d330c313c296fab051317cc5ad4b26319e07");
private static final String DUMMY_CONTROLLER_KEY = "dummy";
- public static final DefaultPluginMetadata PLUGIN_2_2 = create("key2").setName("name2");
- public static final DefaultPluginMetadata PLUGIN_2_1 = create("key1").setName("name2");
- public static final DefaultPluginMetadata PLUGIN_0_0 = create("key0").setName("name0");
+ public static final PluginInfo PLUGIN_2_2 = new PluginInfo("key2").setName("name2");
+ public static final PluginInfo PLUGIN_2_1 = new PluginInfo("key1").setName("name2");
+ public static final PluginInfo PLUGIN_0_0 = new PluginInfo("key0").setName("name0");
private PluginDownloader pluginDownloader = mock(PluginDownloader.class);
- private ServerPluginJarsInstaller serverPluginJarsInstaller = mock(ServerPluginJarsInstaller.class);
- private PendingPluginsWsAction underTest = new PendingPluginsWsAction(pluginDownloader, serverPluginJarsInstaller, new PluginWSCommons());
+ private ServerPluginRepository serverPluginRepository = mock(ServerPluginRepository.class);
+ private PendingPluginsWsAction underTest = new PendingPluginsWsAction(pluginDownloader, serverPluginRepository, new PluginWSCommons());
private Request request = mock(Request.class);
private WsTester.TestResponse response = new WsTester.TestResponse();
@@ -91,7 +91,7 @@ public class PendingPluginsWsActionTest {
@Test
public void verify_properties_displayed_in_json_per_installing_plugin() throws Exception {
- when(pluginDownloader.getDownloadedPlugins()).thenReturn(of(GIT_PLUGIN_METADATA));
+ when(pluginDownloader.getDownloadedPlugins()).thenReturn(of(GIT_PLUGIN_INFO));
underTest.handle(request, response);
@@ -119,7 +119,7 @@ public class PendingPluginsWsActionTest {
@Test
public void verify_properties_displayed_in_json_per_removing_plugin() throws Exception {
- when(serverPluginJarsInstaller.getUninstalledPlugins()).thenReturn(of(GIT_PLUGIN_METADATA));
+ when(serverPluginRepository.getUninstalledPlugins()).thenReturn(of(GIT_PLUGIN_INFO));
underTest.handle(request, response);
@@ -180,7 +180,7 @@ public class PendingPluginsWsActionTest {
@Test
public void removing_plugin_are_sorted_and_unique() throws Exception {
- when(serverPluginJarsInstaller.getUninstalledPlugins()).thenReturn(of(
+ when(serverPluginRepository.getUninstalledPlugins()).thenReturn(of(
PLUGIN_2_2,
PLUGIN_2_1,
PLUGIN_2_2,
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginWSCommonsTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginWSCommonsTest.java
index 831bdbd7b78..e055635b343 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginWSCommonsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginWSCommonsTest.java
@@ -22,7 +22,7 @@ package org.sonar.server.plugins.ws;
import java.io.File;
import org.junit.Test;
import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.core.platform.PluginInfo;
import org.sonar.server.ws.WsTester;
import org.sonar.updatecenter.common.Plugin;
import org.sonar.updatecenter.common.PluginUpdate;
@@ -31,7 +31,6 @@ import org.sonar.updatecenter.common.Version;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.utils.DateUtils.parseDate;
-import static org.sonar.core.plugins.DefaultPluginMetadata.create;
import static org.sonar.server.plugins.ws.PluginWSCommons.toJSon;
import static org.sonar.test.JsonAssert.assertJson;
import static org.sonar.updatecenter.common.PluginUpdate.Status.COMPATIBLE;
@@ -40,14 +39,14 @@ import static org.sonar.updatecenter.common.PluginUpdate.Status.INCOMPATIBLE;
import static org.sonar.updatecenter.common.PluginUpdate.Status.REQUIRE_SONAR_UPGRADE;
public class PluginWSCommonsTest {
- private static final DefaultPluginMetadata GIT_PLUGIN_METADATA = create("scmgit")
+ private static final PluginInfo GIT_PLUGIN_METADATA = new PluginInfo("scmgit")
.setName("Git")
.setDescription("Git SCM Provider.")
- .setVersion("1.0")
+ .setVersion(Version.create("1.0"))
.setLicense("GNU LGPL 3")
- .setOrganization("SonarSource")
+ .setOrganizationName("SonarSource")
.setOrganizationUrl("http://www.sonarsource.com")
- .setHomepage("http://redirect.sonarsource.com/plugins/scmgit.html")
+ .setHomepageUrl("http://redirect.sonarsource.com/plugins/scmgit.html")
.setIssueTrackerUrl("http://jira.codehaus.org/browse/SONARSCGIT")
.setFile(new File("/home/user/sonar-scm-git-plugin-1.0.jar"));
private static final Plugin PLUGIN = new Plugin("p_key")
@@ -202,7 +201,7 @@ public class PluginWSCommonsTest {
PluginUpdate pluginUpdate = new PluginUpdate();
pluginUpdate.setRelease(
new Release(PLUGIN, version("1.0")).addOutgoingDependency(RELEASE)
- );
+ );
jsonWriter.beginObject();
underTest.writeUpdate(jsonWriter, pluginUpdate);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UninstallPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UninstallPluginsWsActionTest.java
index fa8adaa0f98..85a3bba714f 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UninstallPluginsWsActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UninstallPluginsWsActionTest.java
@@ -19,19 +19,15 @@
*/
package org.sonar.server.plugins.ws;
-import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.WebService;
import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.plugins.DefaultPluginMetadata;
import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
+import org.sonar.server.plugins.ServerPluginRepository;
import org.sonar.server.user.MockUserSession;
import org.sonar.server.ws.WsTester;
@@ -45,11 +41,10 @@ public class UninstallPluginsWsActionTest {
private static final String CONTROLLER_KEY = "api/plugins";
private static final String ACTION_KEY = "uninstall";
private static final String KEY_PARAM = "key";
- private static final String PLUGIN_KEY = "pluginKey";
+ private static final String PLUGIN_KEY = "findbugs";
- private PluginRepository pluginRepository = mock(PluginRepository.class);
- private ServerPluginJarsInstaller pluginJarsInstaller = mock(ServerPluginJarsInstaller.class);
- private UninstallPluginsWsAction underTest = new UninstallPluginsWsAction(pluginRepository, pluginJarsInstaller);
+ private ServerPluginRepository pluginRepository = mock(ServerPluginRepository.class);
+ private UninstallPluginsWsAction underTest = new UninstallPluginsWsAction(pluginRepository);
private WsTester wsTester = new WsTester(new PluginsWs(underTest));
private Request invalidRequest = wsTester.newGetRequest(CONTROLLER_KEY, ACTION_KEY);
@@ -109,20 +104,18 @@ public class UninstallPluginsWsActionTest {
@Test
public void IAE_is_raised_when_plugin_is_not_installed() throws Exception {
expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("No plugin with key 'pluginKey'");
+ expectedException.expectMessage("Plugin [findbugs] is not installed");
underTest.handle(validRequest, response);
}
@Test
public void if_plugin_is_installed_uninstallation_is_triggered() throws Exception {
- when(pluginRepository.getMetadata()).thenReturn(ImmutableList.of(
- DefaultPluginMetadata.create(PLUGIN_KEY)
- ));
+ when(pluginRepository.hasPlugin(PLUGIN_KEY)).thenReturn(true);
underTest.handle(validRequest, response);
- verify(pluginJarsInstaller).uninstall(PLUGIN_KEY);
+ verify(pluginRepository).uninstall(PLUGIN_KEY);
assertThat(response.outputAsString()).isEmpty();
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/startup/GeneratePluginIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/startup/GeneratePluginIndexTest.java
index cc96395bc62..8af9cb1eb7c 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/startup/GeneratePluginIndexTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/startup/GeneratePluginIndexTest.java
@@ -25,9 +25,8 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
-import org.sonar.core.plugins.DefaultPluginMetadata;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
import org.sonar.server.platform.DefaultServerFileSystem;
import java.io.File;
@@ -45,8 +44,8 @@ public class GeneratePluginIndexTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- private DefaultServerFileSystem fileSystem;
- private File index;
+ DefaultServerFileSystem fileSystem;
+ File index;
@Before
public void createIndexFile() {
@@ -58,9 +57,9 @@ public class GeneratePluginIndexTest {
@Test
public void shouldWriteIndex() throws IOException {
PluginRepository repository = mock(PluginRepository.class);
- PluginMetadata sqale = newMetadata("sqale");
- PluginMetadata checkstyle = newMetadata("checkstyle");
- when(repository.getMetadata()).thenReturn(Arrays.asList(sqale, checkstyle));
+ PluginInfo sqale = newInfo("sqale");
+ PluginInfo checkstyle = newInfo("checkstyle");
+ when(repository.getPluginInfos()).thenReturn(Arrays.asList(sqale, checkstyle));
new GeneratePluginIndex(fileSystem, repository).start();
@@ -70,11 +69,7 @@ public class GeneratePluginIndexTest {
assertThat(lines.get(1), containsString("checkstyle"));
}
- private PluginMetadata newMetadata(String pluginKey) throws IOException {
- PluginMetadata plugin = mock(DefaultPluginMetadata.class);
- when(plugin.getKey()).thenReturn(pluginKey);
- File pluginFile = temp.newFile(pluginKey + ".jar");
- when(plugin.getFile()).thenReturn(pluginFile);
- return plugin;
+ private PluginInfo newInfo(String pluginKey) throws IOException {
+ return new PluginInfo(pluginKey).setFile(temp.newFile(pluginKey + ".jar"));
}
}
diff --git a/server/sonar-server/src/test/projects/.gitignore b/server/sonar-server/src/test/projects/.gitignore
new file mode 100644
index 00000000000..a945b8525e6
--- /dev/null
+++ b/server/sonar-server/src/test/projects/.gitignore
@@ -0,0 +1,7 @@
+# see README.txt
+!*/target/
+*/target/classes/
+*/target/maven-archiver/
+*/target/maven-status/
+*/target/test-*/
+
diff --git a/server/sonar-server/src/test/projects/README.txt b/server/sonar-server/src/test/projects/README.txt
new file mode 100644
index 00000000000..c53a66d52f2
--- /dev/null
+++ b/server/sonar-server/src/test/projects/README.txt
@@ -0,0 +1,3 @@
+This directory provides the fake plugins used by tests. These tests are rarely changed, so generated
+artifacts are stored in Git repository (see .gitignore). It avoids from adding unnecessary modules
+to build.
diff --git a/server/sonar-server/src/test/projects/pom.xml b/server/sonar-server/src/test/projects/pom.xml
new file mode 100644
index 00000000000..f244768228e
--- /dev/null
+++ b/server/sonar-server/src/test/projects/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+ org.codehaus.sonar.tests
+ parent
+ 0.1-SNAPSHOT
+ pom
+
+ test-base-plugin
+ test-base-plugin-v2
+ test-core-plugin
+ test-extend-plugin
+ test-libs-plugin
+ test-require-plugin
+ test-requirenew-plugin
+
+
+
diff --git a/server/sonar-server/src/test/projects/test-base-plugin-v2/pom.xml b/server/sonar-server/src/test/projects/test-base-plugin-v2/pom.xml
new file mode 100644
index 00000000000..21f7ed5558d
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-base-plugin-v2/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+ org.codehaus.sonar.tests
+ test-base-plugin
+ 0.2-SNAPSHOT
+ sonar-plugin
+ Base Plugin
+ Simple standalone plugin. Used by other fake plugins.
+
+
+
+ org.codehaus.sonar
+ sonar-plugin-api
+ 4.5.4
+ provided
+
+
+
+ src
+
+
+ org.codehaus.sonar
+ sonar-packaging-maven-plugin
+ 1.13
+ true
+
+ testbase
+ BasePlugin
+
+
+
+
+
+
diff --git a/server/sonar-server/src/test/projects/test-base-plugin-v2/src/BasePlugin.java b/server/sonar-server/src/test/projects/test-base-plugin-v2/src/BasePlugin.java
new file mode 100644
index 00000000000..57b4a5dfb98
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-base-plugin-v2/src/BasePlugin.java
@@ -0,0 +1,11 @@
+import org.sonar.api.SonarPlugin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class BasePlugin extends SonarPlugin {
+
+ public List getExtensions() {
+ return Collections.emptyList();
+ }
+}
diff --git a/server/sonar-server/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar b/server/sonar-server/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar
new file mode 100644
index 00000000000..9bd9e0e0fc1
Binary files /dev/null and b/server/sonar-server/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar differ
diff --git a/server/sonar-server/src/test/projects/test-base-plugin/pom.xml b/server/sonar-server/src/test/projects/test-base-plugin/pom.xml
new file mode 100644
index 00000000000..61b994c4754
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-base-plugin/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+ org.codehaus.sonar.tests
+ test-base-plugin
+ 0.1-SNAPSHOT
+ sonar-plugin
+ Base Plugin
+ Simple standalone plugin. Used by other fake plugins.
+
+
+
+ org.codehaus.sonar
+ sonar-plugin-api
+ 4.5.4
+ provided
+
+
+
+ src
+
+
+ org.codehaus.sonar
+ sonar-packaging-maven-plugin
+ 1.13
+ true
+
+ testbase
+ BasePlugin
+
+
+
+
+
+
diff --git a/server/sonar-server/src/test/projects/test-base-plugin/src/BasePlugin.java b/server/sonar-server/src/test/projects/test-base-plugin/src/BasePlugin.java
new file mode 100644
index 00000000000..57b4a5dfb98
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-base-plugin/src/BasePlugin.java
@@ -0,0 +1,11 @@
+import org.sonar.api.SonarPlugin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class BasePlugin extends SonarPlugin {
+
+ public List getExtensions() {
+ return Collections.emptyList();
+ }
+}
diff --git a/server/sonar-server/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar b/server/sonar-server/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar
new file mode 100644
index 00000000000..2a6148ce7b6
Binary files /dev/null and b/server/sonar-server/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar differ
diff --git a/server/sonar-server/src/test/projects/test-core-plugin/pom.xml b/server/sonar-server/src/test/projects/test-core-plugin/pom.xml
new file mode 100644
index 00000000000..fc3f082f6ec
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-core-plugin/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+ org.codehaus.sonar.tests
+ test-core-plugin
+ 0.1-SNAPSHOT
+ sonar-plugin
+ Test Core Plugin
+ Fake core plugin used by tests
+
+
+
+ org.codehaus.sonar
+ sonar-plugin-api
+ 4.5.4
+ provided
+
+
+
+ src
+
+
+ org.codehaus.sonar
+ sonar-packaging-maven-plugin
+ 1.13
+ true
+
+ core
+ CorePlugin
+
+
+
+
+
+
diff --git a/server/sonar-server/src/test/projects/test-core-plugin/src/CorePlugin.java b/server/sonar-server/src/test/projects/test-core-plugin/src/CorePlugin.java
new file mode 100644
index 00000000000..910204d87ea
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-core-plugin/src/CorePlugin.java
@@ -0,0 +1,11 @@
+import org.sonar.api.SonarPlugin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class CorePlugin extends SonarPlugin {
+
+ public List getExtensions() {
+ return Collections.emptyList();
+ }
+}
diff --git a/server/sonar-server/src/test/projects/test-core-plugin/target/test-core-plugin-0.1-SNAPSHOT.jar b/server/sonar-server/src/test/projects/test-core-plugin/target/test-core-plugin-0.1-SNAPSHOT.jar
new file mode 100644
index 00000000000..62eba2aa80f
Binary files /dev/null and b/server/sonar-server/src/test/projects/test-core-plugin/target/test-core-plugin-0.1-SNAPSHOT.jar differ
diff --git a/server/sonar-server/src/test/projects/test-extend-plugin/pom.xml b/server/sonar-server/src/test/projects/test-extend-plugin/pom.xml
new file mode 100644
index 00000000000..9b20de15a6a
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-extend-plugin/pom.xml
@@ -0,0 +1,37 @@
+
+
+ 4.0.0
+ org.codehaus.sonar.tests
+ test-extend-plugin
+ 0.1-SNAPSHOT
+ sonar-plugin
+ Test Extend Plugin
+ Fake plugin that extends the plugin with key "base"
+
+
+
+ org.codehaus.sonar
+ sonar-plugin-api
+ 4.5.4
+ provided
+
+
+
+ src
+
+
+ org.codehaus.sonar
+ sonar-packaging-maven-plugin
+ 1.13
+ true
+
+ testextend
+ ExtendPlugin
+ testbase
+
+
+
+
+
+
diff --git a/server/sonar-server/src/test/projects/test-extend-plugin/src/ExtendPlugin.java b/server/sonar-server/src/test/projects/test-extend-plugin/src/ExtendPlugin.java
new file mode 100644
index 00000000000..826e1842bbb
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-extend-plugin/src/ExtendPlugin.java
@@ -0,0 +1,11 @@
+import org.sonar.api.SonarPlugin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class ExtendPlugin extends SonarPlugin {
+
+ public List getExtensions() {
+ return Collections.emptyList();
+ }
+}
diff --git a/server/sonar-server/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar b/server/sonar-server/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar
new file mode 100644
index 00000000000..7a81fdf0cce
Binary files /dev/null and b/server/sonar-server/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar differ
diff --git a/server/sonar-server/src/test/projects/test-libs-plugin/pom.xml b/server/sonar-server/src/test/projects/test-libs-plugin/pom.xml
new file mode 100644
index 00000000000..e7d242135db
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-libs-plugin/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+ org.codehaus.sonar.tests
+ test-libs-plugin
+ 0.1-SNAPSHOT
+ sonar-plugin
+ Test Libs Plugin
+ Fake plugin that embeds some libraries
+
+
+
+
+ commons-email
+ commons-email
+ 20030310.165926
+
+
+ commons-daemon
+ commons-daemon
+ 1.0.15
+
+
+
+ org.codehaus.sonar
+ sonar-plugin-api
+ 4.5.4
+ provided
+
+
+
+
+ src
+
+
+ org.codehaus.sonar
+ sonar-packaging-maven-plugin
+ 1.13
+ true
+
+ testlibs
+ LibsPlugin
+
+
+
+
+
+
diff --git a/server/sonar-server/src/test/projects/test-libs-plugin/src/LibsPlugin.java b/server/sonar-server/src/test/projects/test-libs-plugin/src/LibsPlugin.java
new file mode 100644
index 00000000000..965c9ac7496
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-libs-plugin/src/LibsPlugin.java
@@ -0,0 +1,11 @@
+import org.sonar.api.SonarPlugin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class LibsPlugin extends SonarPlugin {
+
+ public List getExtensions() {
+ return Collections.emptyList();
+ }
+}
diff --git a/server/sonar-server/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar b/server/sonar-server/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar
new file mode 100644
index 00000000000..85e4772f474
Binary files /dev/null and b/server/sonar-server/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar differ
diff --git a/server/sonar-server/src/test/projects/test-require-plugin/pom.xml b/server/sonar-server/src/test/projects/test-require-plugin/pom.xml
new file mode 100644
index 00000000000..1f77e233f62
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-require-plugin/pom.xml
@@ -0,0 +1,37 @@
+
+
+ 4.0.0
+ org.codehaus.sonar.tests
+ test-require-plugin
+ 0.1-SNAPSHOT
+ sonar-plugin
+ Test Require Plugin
+ This fake plugin depends on test-base-plugin
+
+
+
+ org.codehaus.sonar
+ sonar-plugin-api
+ 4.5.4
+ provided
+
+
+
+ src
+
+
+ org.codehaus.sonar
+ sonar-packaging-maven-plugin
+ 1.13
+ true
+
+ testrequire
+ RequirePlugin
+ testbase:0.1
+
+
+
+
+
+
diff --git a/server/sonar-server/src/test/projects/test-require-plugin/src/RequirePlugin.java b/server/sonar-server/src/test/projects/test-require-plugin/src/RequirePlugin.java
new file mode 100644
index 00000000000..440f73bfb58
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-require-plugin/src/RequirePlugin.java
@@ -0,0 +1,11 @@
+import org.sonar.api.SonarPlugin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class RequirePlugin extends SonarPlugin {
+
+ public List getExtensions() {
+ return Collections.emptyList();
+ }
+}
diff --git a/server/sonar-server/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar b/server/sonar-server/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar
new file mode 100644
index 00000000000..ac1f9f68e46
Binary files /dev/null and b/server/sonar-server/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar differ
diff --git a/server/sonar-server/src/test/projects/test-requirenew-plugin/pom.xml b/server/sonar-server/src/test/projects/test-requirenew-plugin/pom.xml
new file mode 100644
index 00000000000..ca207b10c19
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-requirenew-plugin/pom.xml
@@ -0,0 +1,37 @@
+
+
+ 4.0.0
+ org.codehaus.sonar.tests
+ test-requirenew-plugin
+ 0.1-SNAPSHOT
+ sonar-plugin
+ Test Require New Plugin
+ This fake plugin requires a version of test-base-plugin that is not installed
+
+
+
+ org.codehaus.sonar
+ sonar-plugin-api
+ 4.5.4
+ provided
+
+
+
+ src
+
+
+ org.codehaus.sonar
+ sonar-packaging-maven-plugin
+ 1.13
+ true
+
+ testrequire
+ RequirePlugin
+ testbase:0.2
+
+
+
+
+
+
diff --git a/server/sonar-server/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java b/server/sonar-server/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java
new file mode 100644
index 00000000000..440f73bfb58
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java
@@ -0,0 +1,11 @@
+import org.sonar.api.SonarPlugin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class RequirePlugin extends SonarPlugin {
+
+ public List getExtensions() {
+ return Collections.emptyList();
+ }
+}
diff --git a/server/sonar-server/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar b/server/sonar-server/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar
new file mode 100644
index 00000000000..3437dfee71c
Binary files /dev/null and b/server/sonar-server/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/extension.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/extension.jar
deleted file mode 100644
index e788522ba71..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/extension.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/foo-plugin.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/foo-plugin.jar
deleted file mode 100644
index 7bcf027151a..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/foo-plugin.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/sonar-build-breaker-plugin-0.1.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/sonar-build-breaker-plugin-0.1.jar
deleted file mode 100644
index 0eb5f40bb8c..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/sonar-build-breaker-plugin-0.1.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginDownloaderTest/foo-plugin-1.0.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginDownloaderTest/foo-plugin-1.0.jar
deleted file mode 100644
index 3b3ed4b1b78..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginDownloaderTest/foo-plugin-1.0.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginExtensionMetadataTest/version1/extension.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginExtensionMetadataTest/version1/extension.jar
deleted file mode 100644
index e788522ba71..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginExtensionMetadataTest/version1/extension.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginExtensionMetadataTest/version2/extension.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginExtensionMetadataTest/version2/extension.jar
deleted file mode 100644
index 636176b3092..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginExtensionMetadataTest/version2/extension.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/foo-plugin-1.0.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/foo-plugin-1.0.jar
deleted file mode 100644
index b60ea353a21..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/foo-plugin-1.0.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/foo-plugin-2.0.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/foo-plugin-2.0.jar
deleted file mode 100644
index 2e0488cebdf..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/foo-plugin-2.0.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/not-a-plugin.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/not-a-plugin.jar
deleted file mode 100644
index f35e77146cc..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/not-a-plugin.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/old-plugin.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/old-plugin.jar
deleted file mode 100644
index abb19c057b5..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/old-plugin.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataTest/foo-plugin.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataTest/foo-plugin.jar
deleted file mode 100644
index 7bcf027151a..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataTest/foo-plugin.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/bar-plugin-1.0.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/bar-plugin-1.0.jar
deleted file mode 100644
index acf4fa40269..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/bar-plugin-1.0.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/foo-plugin-1.0.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/foo-plugin-1.0.jar
deleted file mode 100644
index 3b3ed4b1b78..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/foo-plugin-1.0.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/foo-plugin-2.0.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/foo-plugin-2.0.jar
deleted file mode 100644
index b781205e0d0..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/foo-plugin-2.0.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/not-a-plugin.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/not-a-plugin.jar
deleted file mode 100644
index 11b72f4f8eb..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/not-a-plugin.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/require-sq-2.5.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/require-sq-2.5.jar
deleted file mode 100644
index 8044dff8988..00000000000
Binary files a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/require-sq-2.5.jar and /dev/null differ
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar b/server/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/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar and /dev/null differ
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/updatecenter_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/updatecenter_controller.rb
index 555eb77744d..74833832017 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/updatecenter_controller.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/updatecenter_controller.rb
@@ -48,7 +48,7 @@ class Api::UpdatecenterController < Api::ApiController
hash={}
hash['key']=plugin.getKey()
hash['name']=plugin.getName()
- hash['version']=plugin.getVersion() || '-'
+ hash['version']=plugin.getVersion().getName()
hash
end
@@ -58,13 +58,13 @@ class Api::UpdatecenterController < Api::ApiController
xml.plugin do
xml.key(plugin.getKey())
xml.name(plugin.getName())
- xml.version(plugin.getVersion() || '-')
+ xml.version(plugin.getVersion().getName())
end
end
end
end
def user_plugins
- java_facade.getPluginsMetadata().select{|plugin| !plugin.isCore()}.to_a.sort
+ java_facade.getPluginInfos().select{|plugin| !plugin.isCore()}.to_a.sort
end
end
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
index 0f1eea698ea..1575f757006 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
@@ -32,7 +32,7 @@ import org.sonar.api.batch.postjob.PostJob;
import org.sonar.api.batch.postjob.PostJobContext;
import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.platform.ComponentContainer;
+import org.sonar.core.platform.ComponentContainer;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.AnnotationUtils;
import org.sonar.api.utils.dag.DirectAcyclicGraph;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java
new file mode 100644
index 00000000000..6e2c5886c60
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginInstaller.java
@@ -0,0 +1,123 @@
+/*
+ * 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.batch.bootstrap;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.CharUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.Plugin;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.plugins.RemotePlugin;
+import org.sonar.core.plugins.RemotePluginFile;
+import org.sonar.home.cache.FileCache;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Downloads the plugins installed on server and stores them in a local user cache
+ * (see {@link FileCacheProvider}).
+ */
+public class BatchPluginInstaller implements PluginInstaller {
+
+ private static final Logger LOG = Loggers.get(BatchPluginInstaller.class);
+
+ private final ServerClient server;
+ private final FileCache fileCache;
+ private final BatchPluginPredicate pluginPredicate;
+
+ public BatchPluginInstaller(ServerClient server, FileCache fileCache, BatchPluginPredicate pluginPredicate) {
+ this.server = server;
+ this.fileCache = fileCache;
+ this.pluginPredicate = pluginPredicate;
+ }
+
+ @Override
+ public Map installRemotes() {
+ Map infosByKey = new HashMap<>();
+ for (RemotePlugin remotePlugin : listRemotePlugins()) {
+ if (pluginPredicate.apply(remotePlugin.getKey())) {
+ File jarFile = download(remotePlugin);
+ PluginInfo info = PluginInfo.create(jarFile);
+ infosByKey.put(info.getKey(), info);
+ }
+ }
+ return infosByKey;
+ }
+
+ /**
+ * Returns empty on purpose. This method is used only by tests.
+ * @see org.sonar.batch.mediumtest.BatchMediumTester
+ */
+ @Override
+ public Map installLocals() {
+ return Collections.emptyMap();
+ }
+
+ @VisibleForTesting
+ File download(final RemotePlugin remote) {
+ try {
+ final RemotePluginFile file = remote.file();
+ return fileCache.get(file.getFilename(), file.getHash(), new FileCache.Downloader() {
+ @Override
+ public void download(String filename, File toFile) throws IOException {
+ String url = "/deploy/plugins/" + remote.getKey() + "/" + file.getFilename();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Download {} to {}", url, toFile.getAbsolutePath());
+ } else {
+ LOG.info("Download {}", file.getFilename());
+ }
+ server.download(url, toFile);
+ }
+ });
+
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to download plugin: " + remote.getKey(), e);
+ }
+ }
+
+ /**
+ * Gets information about the plugins installed on server (filename, checksum)
+ */
+ @VisibleForTesting
+ List listRemotePlugins() {
+ String url = "/deploy/plugins/index.txt";
+ try {
+ LOG.debug("Download index of plugins");
+ String indexContent = server.request(url);
+ String[] rows = StringUtils.split(indexContent, CharUtils.LF);
+ List result = Lists.newArrayList();
+ for (String row : rows) {
+ result.add(RemotePlugin.unmarshal(row));
+ }
+ return result;
+
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to download list of plugins: " + url, e);
+ }
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginJarInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginJarInstaller.java
deleted file mode 100644
index 8866cf7fc0f..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginJarInstaller.java
+++ /dev/null
@@ -1,49 +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.batch.bootstrap;
-
-import org.sonar.api.BatchComponent;
-import org.sonar.core.plugins.DefaultPluginMetadata;
-import org.sonar.core.plugins.PluginJarInstaller;
-import org.sonar.home.cache.FileCache;
-
-import java.io.File;
-import java.io.IOException;
-
-public class BatchPluginJarInstaller extends PluginJarInstaller implements BatchComponent {
-
- private FileCache cache;
-
- public BatchPluginJarInstaller(FileCache cache) {
- this.cache = cache;
- }
-
- public DefaultPluginMetadata installToCache(File pluginFile, boolean isCore) {
- DefaultPluginMetadata metadata = extractMetadata(pluginFile, isCore);
- install(metadata, null, pluginFile);
- return metadata;
- }
-
- @Override
- protected File extractPluginDependencies(File pluginFile, File pluginBasedir) throws IOException {
- return cache.unzip(pluginFile);
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginPredicate.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginPredicate.java
new file mode 100644
index 00000000000..f283dcd7247
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginPredicate.java
@@ -0,0 +1,121 @@
+/*
+ * 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.batch.bootstrap;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+
+import javax.annotation.Nonnull;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Sets.newHashSet;
+
+/**
+ * Filters the plugins to be enabled during analysis
+ */
+public class BatchPluginPredicate implements Predicate, BatchComponent {
+
+ private static final Logger LOG = Loggers.get(BatchPluginPredicate.class);
+
+ private static final String CORE_PLUGIN_KEY = "core";
+ private static final String BUILDBREAKER_PLUGIN_KEY = "buildbreaker";
+ private static final String PROPERTY_IS_DEPRECATED_MSG = "Property {0} is deprecated. Please use {1} instead.";
+
+ private final Set whites = newHashSet(), blacks = newHashSet();
+ private final DefaultAnalysisMode mode;
+
+ public BatchPluginPredicate(Settings settings, DefaultAnalysisMode mode) {
+ this.mode = mode;
+ if (settings.hasKey(CoreProperties.BATCH_INCLUDE_PLUGINS)) {
+ whites.addAll(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_INCLUDE_PLUGINS)));
+ }
+ if (settings.hasKey(CoreProperties.BATCH_EXCLUDE_PLUGINS)) {
+ blacks.addAll(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_EXCLUDE_PLUGINS)));
+ }
+ if (mode.isPreview()) {
+ // These default values are not supported by Settings because the class CorePlugin
+ // is not loaded yet.
+ if (settings.hasKey(CoreProperties.DRY_RUN_INCLUDE_PLUGINS)) {
+ LOG.warn(MessageFormat.format(PROPERTY_IS_DEPRECATED_MSG, CoreProperties.DRY_RUN_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS));
+ whites.addAll(propertyValues(settings,
+ CoreProperties.DRY_RUN_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE));
+ } else {
+ whites.addAll(propertyValues(settings,
+ CoreProperties.PREVIEW_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE));
+ }
+ if (settings.hasKey(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS)) {
+ LOG.warn(MessageFormat.format(PROPERTY_IS_DEPRECATED_MSG, CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS));
+ blacks.addAll(propertyValues(settings,
+ CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE));
+ } else {
+ blacks.addAll(propertyValues(settings,
+ CoreProperties.PREVIEW_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE));
+ }
+ }
+ if (!whites.isEmpty()) {
+ LOG.info("Include plugins: " + Joiner.on(", ").join(whites));
+ }
+ if (!blacks.isEmpty()) {
+ LOG.info("Exclude plugins: " + Joiner.on(", ").join(blacks));
+ }
+ }
+
+ @Override
+ public boolean apply(@Nonnull String pluginKey) {
+ if (CORE_PLUGIN_KEY.equals(pluginKey)) {
+ return !mode.isMediumTest();
+ }
+
+ if (BUILDBREAKER_PLUGIN_KEY.equals(pluginKey) && mode.isPreview()) {
+ LOG.info("Build Breaker plugin is no more supported in preview/incremental mode");
+ return false;
+ }
+
+ // FIXME what happens if there are only white-listed plugins ?
+ List mergeList = newArrayList(blacks);
+ mergeList.removeAll(whites);
+ return mergeList.isEmpty() || !mergeList.contains(pluginKey);
+ }
+
+ Set getWhites() {
+ return whites;
+ }
+
+ Set getBlacks() {
+ return blacks;
+ }
+
+ static List propertyValues(Settings settings, String key, String defaultValue) {
+ String s = StringUtils.defaultIfEmpty(settings.getString(key), defaultValue);
+ return Lists.newArrayList(Splitter.on(",").trimResults().split(s));
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java
index b8a44c0d97c..b20c85114ed 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java
@@ -19,174 +19,69 @@
*/
package org.sonar.batch.bootstrap;
-import com.google.common.base.Joiner;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.CoreProperties;
+import org.picocontainer.Startable;
import org.sonar.api.Plugin;
-import org.sonar.api.SonarPlugin;
-import org.sonar.api.config.Settings;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
-import org.sonar.core.plugins.PluginClassloaders;
-import org.sonar.core.plugins.RemotePlugin;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginLoader;
+import org.sonar.core.platform.PluginRepository;
-import java.io.File;
-import java.text.MessageFormat;
-import java.util.*;
+import java.util.Collection;
+import java.util.Map;
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Sets.newHashSet;
+public class BatchPluginRepository implements PluginRepository, Startable {
-public class BatchPluginRepository implements PluginRepository {
+ private final PluginInstaller installer;
+ private final PluginLoader loader;
- private static final Logger LOG = LoggerFactory.getLogger(BatchPluginRepository.class);
- private static final String CORE_PLUGIN = "core";
+ private Map pluginInstancesByKeys;
+ private Map infosByKeys;
- private PluginsRepository pluginsReferential;
- private Map pluginsByKey;
- private Map metadataByKey;
- private Settings settings;
- private PluginClassloaders classLoaders;
- private final DefaultAnalysisMode analysisMode;
- private final BatchPluginJarInstaller pluginInstaller;
-
- public BatchPluginRepository(PluginsRepository pluginsReferential, Settings settings, DefaultAnalysisMode analysisMode,
- BatchPluginJarInstaller pluginInstaller) {
- this.pluginsReferential = pluginsReferential;
- this.settings = settings;
- this.analysisMode = analysisMode;
- this.pluginInstaller = pluginInstaller;
+ public BatchPluginRepository(PluginInstaller installer, PluginLoader loader) {
+ this.installer = installer;
+ this.loader = loader;
}
+ @Override
public void start() {
- LOG.info("Install plugins");
- doStart(pluginsReferential.pluginList());
-
- Map localPlugins = pluginsReferential.localPlugins();
- if (!localPlugins.isEmpty()) {
- LOG.info("Install local plugins");
- for (Map.Entry pluginByMetadata : localPlugins.entrySet()) {
- metadataByKey.put(pluginByMetadata.getKey().getKey(), pluginByMetadata.getKey());
- pluginsByKey.put(pluginByMetadata.getKey().getKey(), pluginByMetadata.getValue());
- }
- }
- }
+ infosByKeys = installer.installRemotes();
+ pluginInstancesByKeys = loader.load(infosByKeys);
- void doStart(List remotePlugins) {
- PluginFilter filter = new PluginFilter(settings, analysisMode);
- metadataByKey = Maps.newHashMap();
- for (RemotePlugin remote : remotePlugins) {
- if (filter.accepts(remote.getKey())) {
- File pluginFile = pluginsReferential.pluginFile(remote);
- PluginMetadata metadata = pluginInstaller.installToCache(pluginFile, remote.isCore());
- if (StringUtils.isBlank(metadata.getBasePlugin()) || filter.accepts(metadata.getBasePlugin())) {
- metadataByKey.put(metadata.getKey(), metadata);
- } else {
- LOG.debug("Excluded plugin: " + metadata.getKey());
- }
- }
+ // this part is only used by tests
+ for (Map.Entry entry : installer.installLocals().entrySet()) {
+ String pluginKey = entry.getKey();
+ infosByKeys.put(pluginKey, new PluginInfo(pluginKey));
+ pluginInstancesByKeys.put(pluginKey, entry.getValue());
}
- classLoaders = new PluginClassloaders(Thread.currentThread().getContextClassLoader());
- pluginsByKey = classLoaders.init(metadataByKey.values());
}
+ @Override
public void stop() {
- if (classLoaders != null) {
- classLoaders.clean();
- classLoaders = null;
- }
- }
+ // close plugin classloaders
+ loader.unload(pluginInstancesByKeys.values());
- @Override
- public Plugin getPlugin(String key) {
- return pluginsByKey.get(key);
+ pluginInstancesByKeys.clear();
+ infosByKeys.clear();
}
@Override
- public Collection getMetadata() {
- return metadataByKey.values();
+ public Collection getPluginInfos() {
+ return infosByKeys.values();
}
@Override
- public PluginMetadata getMetadata(String pluginKey) {
- return metadataByKey.get(pluginKey);
+ public PluginInfo getPluginInfo(String key) {
+ // TODO check null result
+ return infosByKeys.get(key);
}
- public Map getPluginsByMetadata() {
- Map result = Maps.newHashMap();
- for (Map.Entry entry : metadataByKey.entrySet()) {
- String pluginKey = entry.getKey();
- PluginMetadata metadata = entry.getValue();
- result.put(metadata, pluginsByKey.get(pluginKey));
- }
- return result;
+ @Override
+ public Plugin getPluginInstance(String key) {
+ // TODO check null result
+ return pluginInstancesByKeys.get(key);
}
- static class PluginFilter {
- private static final String BUILDBREAKER_PLUGIN_KEY = "buildbreaker";
- private static final String PROPERTY_IS_DEPRECATED_MSG = "Property {0} is deprecated. Please use {1} instead.";
- Set whites = newHashSet(), blacks = newHashSet();
- private DefaultAnalysisMode mode;
-
- PluginFilter(Settings settings, DefaultAnalysisMode mode) {
- this.mode = mode;
- if (settings.hasKey(CoreProperties.BATCH_INCLUDE_PLUGINS)) {
- whites.addAll(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_INCLUDE_PLUGINS)));
- }
- if (settings.hasKey(CoreProperties.BATCH_EXCLUDE_PLUGINS)) {
- blacks.addAll(Arrays.asList(settings.getStringArray(CoreProperties.BATCH_EXCLUDE_PLUGINS)));
- }
- if (mode.isPreview()) {
- // These default values are not supported by Settings because the class CorePlugin
- // is not loaded yet.
- if (settings.hasKey(CoreProperties.DRY_RUN_INCLUDE_PLUGINS)) {
- LOG.warn(MessageFormat.format(PROPERTY_IS_DEPRECATED_MSG, CoreProperties.DRY_RUN_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS));
- whites.addAll(propertyValues(settings,
- CoreProperties.DRY_RUN_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE));
- } else {
- whites.addAll(propertyValues(settings,
- CoreProperties.PREVIEW_INCLUDE_PLUGINS, CoreProperties.PREVIEW_INCLUDE_PLUGINS_DEFAULT_VALUE));
- }
- if (settings.hasKey(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS)) {
- LOG.warn(MessageFormat.format(PROPERTY_IS_DEPRECATED_MSG, CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS));
- blacks.addAll(propertyValues(settings,
- CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE));
- } else {
- blacks.addAll(propertyValues(settings,
- CoreProperties.PREVIEW_EXCLUDE_PLUGINS, CoreProperties.PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE));
- }
- }
- if (!whites.isEmpty()) {
- LOG.info("Include plugins: " + Joiner.on(", ").join(whites));
- }
- if (!blacks.isEmpty()) {
- LOG.info("Exclude plugins: " + Joiner.on(", ").join(blacks));
- }
- }
-
- static List propertyValues(Settings settings, String key, String defaultValue) {
- String s = StringUtils.defaultIfEmpty(settings.getString(key), defaultValue);
- return Lists.newArrayList(Splitter.on(",").trimResults().split(s));
- }
-
- boolean accepts(String pluginKey) {
- if (CORE_PLUGIN.equals(pluginKey)) {
- return !mode.isMediumTest();
- }
-
- if (BUILDBREAKER_PLUGIN_KEY.equals(pluginKey) && mode.isPreview()) {
- LOG.info("Build Breaker plugin is no more supported in preview/incremental mode");
- return false;
- }
-
- List mergeList = newArrayList(blacks);
- mergeList.removeAll(whites);
- return mergeList.isEmpty() || !mergeList.contains(pluginKey);
- }
+ @Override
+ public boolean hasPlugin(String key) {
+ return infosByKeys.containsKey(key);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginUnzipper.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginUnzipper.java
new file mode 100644
index 00000000000..29f554ddc89
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginUnzipper.java
@@ -0,0 +1,77 @@
+/*
+ * 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.batch.bootstrap;
+
+import org.apache.commons.io.FileUtils;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.utils.ZipUtils;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginUnzipper;
+import org.sonar.core.platform.UnzippedPlugin;
+import org.sonar.home.cache.FileCache;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class BatchPluginUnzipper extends PluginUnzipper implements BatchComponent {
+
+ private final FileCache fileCache;
+
+ public BatchPluginUnzipper(FileCache fileCache) {
+ this.fileCache = fileCache;
+ }
+
+ @Override
+ public UnzippedPlugin unzip(PluginInfo info) {
+ try {
+ File dir = unzipFile(info.getFile());
+ return UnzippedPlugin.createFromUnzippedDir(info.getKey(), info.getFile(), dir);
+ } catch (Exception e) {
+ throw new IllegalStateException(String.format("Fail to open plugin [%s]: %s", info.getKey(), info.getFile().getAbsolutePath()), e);
+ }
+ }
+
+ private File unzipFile(File cachedFile) throws IOException {
+ String filename = cachedFile.getName();
+ File destDir = new File(cachedFile.getParentFile(), filename + "_unzip");
+ File lockFile = new File(cachedFile.getParentFile(), filename + "_unzip.lock");
+ if (!destDir.exists()) {
+ FileOutputStream out = new FileOutputStream(lockFile);
+ try {
+ java.nio.channels.FileLock lock = out.getChannel().lock();
+ try {
+ // Recheck in case of concurrent processes
+ if (!destDir.exists()) {
+ File tempDir = fileCache.createTempDir();
+ ZipUtils.unzip(cachedFile, tempDir, newLibFilter());
+ FileUtils.moveDirectory(tempDir, destDir);
+ }
+ } finally {
+ lock.release();
+ }
+ } finally {
+ out.close();
+ FileUtils.deleteQuietly(lockFile);
+ }
+ }
+ return destDir;
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DefaultPluginsRepository.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DefaultPluginsRepository.java
deleted file mode 100644
index 2687ebc56df..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DefaultPluginsRepository.java
+++ /dev/null
@@ -1,99 +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.batch.bootstrap;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.lang.CharUtils;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.SonarPlugin;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.core.plugins.RemotePlugin;
-import org.sonar.core.plugins.RemotePluginFile;
-import org.sonar.home.cache.FileCache;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A {@link PluginsRepository} implementation that put downloaded plugins in a FS cache.
- */
-public class DefaultPluginsRepository implements PluginsRepository {
-
- private static final Logger LOG = LoggerFactory.getLogger(DefaultPluginsRepository.class);
-
- private ServerClient server;
- private FileCache fileCache;
-
- public DefaultPluginsRepository(FileCache fileCache, ServerClient server) {
- this.server = server;
- this.fileCache = fileCache;
- }
-
- @Override
- public File pluginFile(final RemotePlugin remote) {
- try {
- final RemotePluginFile file = remote.file();
- return fileCache.get(file.getFilename(), file.getHash(), new FileCache.Downloader() {
- @Override
- public void download(String filename, File toFile) throws IOException {
- String url = "/deploy/plugins/" + remote.getKey() + "/" + file.getFilename();
- if (LOG.isDebugEnabled()) {
- LOG.debug("Download {} to {}", url, toFile.getAbsolutePath());
- } else {
- LOG.info("Download {}", file.getFilename());
- }
- server.download(url, toFile);
- }
- });
-
- } catch (Exception e) {
- throw new IllegalStateException("Fail to download plugin: " + remote.getKey(), e);
- }
- }
-
- @Override
- public List pluginList() {
- String url = "/deploy/plugins/index.txt";
- try {
- LOG.debug("Download index of plugins");
- String indexContent = server.request(url);
- String[] rows = StringUtils.split(indexContent, CharUtils.LF);
- List remoteLocations = Lists.newArrayList();
- for (String row : rows) {
- remoteLocations.add(RemotePlugin.unmarshal(row));
- }
- return remoteLocations;
-
- } catch (Exception e) {
- throw new IllegalStateException("Fail to download plugins index: " + url, e);
- }
- }
-
- @Override
- public Map localPlugins() {
- return Collections.emptyMap();
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
index 86599f96774..165aa83e649 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ExtensionInstaller.java
@@ -21,22 +21,22 @@ package org.sonar.batch.bootstrap;
import org.sonar.api.ExtensionProvider;
import org.sonar.api.Plugin;
-import org.sonar.api.platform.ComponentContainer;
-import org.sonar.api.platform.PluginMetadata;
import org.sonar.batch.bootstrapper.EnvironmentInformation;
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
import javax.annotation.Nullable;
import java.util.List;
-import java.util.Map;
public class ExtensionInstaller {
- private final BatchPluginRepository pluginRepository;
+ private final PluginRepository pluginRepository;
private final EnvironmentInformation env;
private final DefaultAnalysisMode analysisMode;
- public ExtensionInstaller(BatchPluginRepository pluginRepository, EnvironmentInformation env, DefaultAnalysisMode analysisMode) {
+ public ExtensionInstaller(PluginRepository pluginRepository, EnvironmentInformation env, DefaultAnalysisMode analysisMode) {
this.pluginRepository = pluginRepository;
this.env = env;
this.analysisMode = analysisMode;
@@ -50,11 +50,10 @@ public class ExtensionInstaller {
}
// plugin extensions
- for (Map.Entry entry : pluginRepository.getPluginsByMetadata().entrySet()) {
- PluginMetadata metadata = entry.getKey();
- Plugin plugin = entry.getValue();
+ for (PluginInfo pluginInfo : pluginRepository.getPluginInfos()) {
+ Plugin plugin = pluginRepository.getPluginInstance(pluginInfo.getKey());
for (Object extension : plugin.getExtensions()) {
- doInstall(container, matcher, metadata, extension);
+ doInstall(container, matcher, pluginInfo, extension);
}
}
List providers = container.getComponentsByType(ExtensionProvider.class);
@@ -71,13 +70,13 @@ public class ExtensionInstaller {
return this;
}
- private void doInstall(ComponentContainer container, ExtensionMatcher matcher, @Nullable PluginMetadata metadata, Object extension) {
+ private void doInstall(ComponentContainer container, ExtensionMatcher matcher, @Nullable PluginInfo pluginInfo, Object extension) {
if (ExtensionUtils.supportsEnvironment(extension, env)
&& (analysisMode.isDb() || !ExtensionUtils.requiresDB(extension))
&& matcher.accept(extension)) {
- container.addExtension(metadata, extension);
+ container.addExtension(pluginInfo, extension);
} else {
- container.declareExtension(metadata, extension);
+ container.declareExtension(pluginInfo, extension);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java
index 7aaf0f6be32..09d217122af 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java
@@ -21,28 +21,44 @@ package org.sonar.batch.bootstrap;
import org.sonar.api.Plugin;
import org.sonar.api.config.EmailSettings;
-import org.sonar.api.platform.ComponentContainer;
-import org.sonar.api.platform.PluginMetadata;
import org.sonar.api.utils.Durations;
-import org.sonar.core.util.DefaultHttpDownloader;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.UriReader;
import org.sonar.api.utils.internal.TempFolderCleaner;
import org.sonar.batch.components.PastSnapshotFinder;
-import org.sonar.batch.deprecated.components.*;
+import org.sonar.batch.deprecated.components.PastSnapshotFinderByDate;
+import org.sonar.batch.deprecated.components.PastSnapshotFinderByDays;
+import org.sonar.batch.deprecated.components.PastSnapshotFinderByPreviousAnalysis;
+import org.sonar.batch.deprecated.components.PastSnapshotFinderByPreviousVersion;
+import org.sonar.batch.deprecated.components.PastSnapshotFinderByVersion;
import org.sonar.batch.issue.tracking.DefaultServerLineHashesLoader;
import org.sonar.batch.issue.tracking.ServerLineHashesLoader;
import org.sonar.batch.platform.DefaultServer;
-import org.sonar.batch.repository.*;
+import org.sonar.batch.repository.DefaultGlobalRepositoriesLoader;
+import org.sonar.batch.repository.DefaultProjectRepositoriesLoader;
+import org.sonar.batch.repository.DefaultServerIssuesLoader;
+import org.sonar.batch.repository.GlobalRepositoriesLoader;
+import org.sonar.batch.repository.GlobalRepositoriesProvider;
+import org.sonar.batch.repository.ProjectRepositoriesLoader;
+import org.sonar.batch.repository.ServerIssuesLoader;
import org.sonar.batch.repository.user.UserRepository;
import org.sonar.core.cluster.NullQueue;
import org.sonar.core.config.Logback;
import org.sonar.core.i18n.DefaultI18n;
import org.sonar.core.i18n.RuleI18nManager;
-import org.sonar.core.persistence.*;
+import org.sonar.core.persistence.DaoUtils;
+import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.persistence.SemaphoreUpdater;
+import org.sonar.core.persistence.SemaphoresImpl;
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginLoader;
+import org.sonar.core.platform.PluginRepository;
import org.sonar.core.purge.PurgeProfiler;
import org.sonar.core.rule.CacheRuleFinder;
import org.sonar.core.user.HibernateUserFinder;
+import org.sonar.core.util.DefaultHttpDownloader;
import org.sonar.jpa.dao.MeasuresDao;
import org.sonar.jpa.session.DefaultDatabaseConnector;
import org.sonar.jpa.session.JpaDatabaseSession;
@@ -79,11 +95,15 @@ public class GlobalContainer extends ComponentContainer {
private void addBootstrapComponents() {
add(
+ // plugins
BatchPluginRepository.class,
- BatchPluginJarInstaller.class,
+ PluginLoader.class,
+ BatchPluginUnzipper.class,
+ BatchPluginPredicate.class,
+ ExtensionInstaller.class,
+
GlobalSettings.class,
ServerClient.class,
- ExtensionInstaller.class,
Logback.class,
DefaultServer.class,
new TempFolderProvider(),
@@ -95,20 +115,16 @@ public class GlobalContainer extends ComponentContainer {
DefaultI18n.class,
new GlobalRepositoriesProvider(),
UserRepository.class);
- if (getComponentByType(PluginsRepository.class) == null) {
- add(DefaultPluginsRepository.class);
- }
- if (getComponentByType(GlobalRepositoriesLoader.class) == null) {
- add(DefaultGlobalRepositoriesLoader.class);
- }
- if (getComponentByType(ProjectRepositoriesLoader.class) == null) {
- add(DefaultProjectRepositoriesLoader.class);
- }
- if (getComponentByType(ServerIssuesLoader.class) == null) {
- add(DefaultServerIssuesLoader.class);
- }
- if (getComponentByType(ServerLineHashesLoader.class) == null) {
- add(DefaultServerLineHashesLoader.class);
+ addIfMissing(BatchPluginInstaller.class, PluginInstaller.class);
+ addIfMissing(DefaultGlobalRepositoriesLoader.class, GlobalRepositoriesLoader.class);
+ addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class);
+ addIfMissing(DefaultServerIssuesLoader.class, ServerIssuesLoader.class);
+ addIfMissing(DefaultServerLineHashesLoader.class, ServerLineHashesLoader.class);
+ }
+
+ public void addIfMissing(Object object, Class objectType) {
+ if (getComponentByType(objectType) == null) {
+ add(object);
}
}
@@ -147,10 +163,10 @@ public class GlobalContainer extends ComponentContainer {
}
private void installPlugins() {
- for (Map.Entry entry : getComponentByType(BatchPluginRepository.class).getPluginsByMetadata().entrySet()) {
- PluginMetadata metadata = entry.getKey();
- Plugin plugin = entry.getValue();
- addExtension(metadata, plugin);
+ PluginRepository pluginRepository = getComponentByType(PluginRepository.class);
+ for (PluginInfo pluginInfo : pluginRepository.getPluginInfos()) {
+ Plugin instance = pluginRepository.getPluginInstance(pluginInfo.getKey());
+ addExtension(pluginInfo, instance);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PluginInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PluginInstaller.java
new file mode 100644
index 00000000000..97eb513d4a6
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PluginInstaller.java
@@ -0,0 +1,42 @@
+/*
+ * 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.batch.bootstrap;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.api.Plugin;
+import org.sonar.core.platform.PluginInfo;
+
+import java.util.Map;
+
+public interface PluginInstaller extends BatchComponent {
+
+ /**
+ * Gets the list of plugins installed on server and downloads them if not
+ * already in local cache.
+ * @return information about all installed plugins, grouped by key
+ */
+ Map installRemotes();
+
+ /**
+ * Used only by tests.
+ * @see org.sonar.batch.mediumtest.BatchMediumTester
+ */
+ Map installLocals();
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PluginsRepository.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PluginsRepository.java
deleted file mode 100644
index 58473fd6af1..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PluginsRepository.java
+++ /dev/null
@@ -1,51 +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.batch.bootstrap;
-
-import org.sonar.api.SonarPlugin;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.core.plugins.RemotePlugin;
-
-import java.io.File;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Plugin referential.
- * @since 4.4
- */
-public interface PluginsRepository {
-
- /**
- * Return list of remote plugins to be installed
- */
- List pluginList();
-
- /**
- * Return location of a given plugin on the local FS.
- */
- File pluginFile(RemotePlugin remote);
-
- /**
- * Return the list of local plugins to be installed
- */
- Map localPlugins();
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java
index b3fd7e46392..fce09a6cd1c 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TaskContainer.java
@@ -23,7 +23,7 @@ import org.sonar.batch.components.PastMeasuresLoader;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.CoreProperties;
-import org.sonar.api.platform.ComponentContainer;
+import org.sonar.core.platform.ComponentContainer;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.task.Task;
import org.sonar.api.task.TaskComponent;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
index e274375076b..09871955a38 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
@@ -28,27 +28,31 @@ import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.batch.debt.internal.DefaultDebtModel;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.batch.bootstrap.PluginsRepository;
import org.sonar.batch.bootstrap.TaskProperties;
import org.sonar.batch.bootstrapper.Batch;
import org.sonar.batch.bootstrapper.EnvironmentInformation;
import org.sonar.batch.issue.tracking.ServerLineHashesLoader;
-import org.sonar.batch.protocol.input.*;
+import org.sonar.batch.protocol.input.ActiveRule;
import org.sonar.batch.protocol.input.BatchInput.ServerIssue;
+import org.sonar.batch.protocol.input.FileData;
+import org.sonar.batch.protocol.input.GlobalRepositories;
+import org.sonar.batch.protocol.input.ProjectRepositories;
import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.repository.GlobalRepositoriesLoader;
import org.sonar.batch.repository.ProjectRepositoriesLoader;
import org.sonar.batch.repository.ServerIssuesLoader;
import org.sonar.core.component.ComponentKeys;
-import org.sonar.core.plugins.DefaultPluginMetadata;
-import org.sonar.core.plugins.RemotePlugin;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
/**
* Main utility class for writing batch medium tests.
@@ -70,22 +74,22 @@ public class BatchMediumTester {
public static class BatchMediumTesterBuilder {
private final FakeGlobalRepositoriesLoader globalRefProvider = new FakeGlobalRepositoriesLoader();
private final FakeProjectRepositoriesLoader projectRefProvider = new FakeProjectRepositoriesLoader();
- private final FakePluginsRepository pluginsReferential = new FakePluginsRepository();
+ private final FakePluginInstaller pluginInstaller = new FakePluginInstaller();
private final FakeServerIssuesLoader serverIssues = new FakeServerIssuesLoader();
private final FakeServerLineHashesLoader serverLineHashes = new FakeServerLineHashesLoader();
- private final Map bootstrapProperties = new HashMap();
+ private final Map bootstrapProperties = new HashMap<>();
public BatchMediumTester build() {
return new BatchMediumTester(this);
}
public BatchMediumTesterBuilder registerPlugin(String pluginKey, File location) {
- pluginsReferential.addPlugin(pluginKey, location);
+ pluginInstaller.add(pluginKey, location);
return this;
}
public BatchMediumTesterBuilder registerPlugin(String pluginKey, SonarPlugin instance) {
- pluginsReferential.addPlugin(pluginKey, instance);
+ pluginInstaller.add(pluginKey, instance);
return this;
}
@@ -164,7 +168,7 @@ public class BatchMediumTester {
.setEnableLoggingConfiguration(true)
.addComponents(
new EnvironmentInformation("mediumTest", "1.0"),
- builder.pluginsReferential,
+ builder.pluginInstaller,
builder.globalRefProvider,
builder.projectRefProvider,
builder.serverIssues,
@@ -280,41 +284,6 @@ public class BatchMediumTester {
}
- private static class FakePluginsRepository implements PluginsRepository {
-
- private List pluginList = new ArrayList();
- private Map pluginFiles = new HashMap();
- Map localPlugins = new HashMap();
-
- @Override
- public List pluginList() {
- return pluginList;
- }
-
- @Override
- public File pluginFile(RemotePlugin remote) {
- return pluginFiles.get(remote);
- }
-
- public FakePluginsRepository addPlugin(String pluginKey, File location) {
- RemotePlugin plugin = new RemotePlugin(pluginKey, false);
- pluginList.add(plugin);
- pluginFiles.put(plugin, location);
- return this;
- }
-
- public FakePluginsRepository addPlugin(String pluginKey, SonarPlugin pluginInstance) {
- localPlugins.put(DefaultPluginMetadata.create(pluginKey), pluginInstance);
- return this;
- }
-
- @Override
- public Map localPlugins() {
- return localPlugins;
- }
-
- }
-
private static class FakeServerIssuesLoader implements ServerIssuesLoader {
private List serverIssues = new ArrayList<>();
diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/FakePluginInstaller.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/FakePluginInstaller.java
new file mode 100644
index 00000000000..cbd837c66c9
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/FakePluginInstaller.java
@@ -0,0 +1,54 @@
+/*
+ * 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.batch.mediumtest;
+
+import org.sonar.api.Plugin;
+import org.sonar.batch.bootstrap.PluginInstaller;
+import org.sonar.core.platform.PluginInfo;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+public class FakePluginInstaller implements PluginInstaller {
+
+ private final Map infosByKeys = new HashMap<>();
+ private final Map instancesByKeys = new HashMap<>();
+
+ public FakePluginInstaller add(String pluginKey, File jarFile) {
+ infosByKeys.put(pluginKey, PluginInfo.create(jarFile));
+ return this;
+ }
+
+ public FakePluginInstaller add(String pluginKey, Plugin instance) {
+ instancesByKeys.put(pluginKey, instance);
+ return this;
+ }
+
+ @Override
+ public Map installRemotes() {
+ return infosByKeys;
+ }
+
+ @Override
+ public Map installLocals() {
+ return instancesByKeys;
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
index 75281a9e961..f8312429543 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
@@ -27,7 +27,7 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.batch.rule.CheckFactory;
import org.sonar.api.checks.NoSonarFilter;
-import org.sonar.api.platform.ComponentContainer;
+import org.sonar.core.platform.ComponentContainer;
import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.FileExclusions;
import org.sonar.batch.ProjectTree;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
index ebf3d5c2d87..12a23bf62e4 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
@@ -26,7 +26,7 @@ import org.sonar.api.batch.InstantiationStrategy;
import org.sonar.api.batch.bootstrap.ProjectBootstrapper;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.config.Settings;
-import org.sonar.api.platform.ComponentContainer;
+import org.sonar.core.platform.ComponentContainer;
import org.sonar.api.resources.Languages;
import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.PathResolver;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java
index 0064d028ea8..bb3f0f8a021 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ScanTask.java
@@ -20,7 +20,7 @@
package org.sonar.batch.scan;
import org.sonar.api.CoreProperties;
-import org.sonar.api.platform.ComponentContainer;
+import org.sonar.core.platform.ComponentContainer;
import org.sonar.api.task.Task;
import org.sonar.api.task.TaskDefinition;
import org.sonar.batch.DefaultProjectTree;
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
index 14fde3895ef..6f7e0c11e32 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchExtensionDictionnaryTest.java
@@ -24,7 +24,7 @@ import org.junit.Test;
import org.sonar.api.BatchExtension;
import org.sonar.api.batch.*;
import org.sonar.api.batch.postjob.PostJobContext;
-import org.sonar.api.platform.ComponentContainer;
+import org.sonar.core.platform.ComponentContainer;
import org.sonar.api.resources.Project;
import org.sonar.batch.postjob.PostJobOptimizer;
import org.sonar.batch.sensor.DefaultSensorContext;
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java
new file mode 100644
index 00000000000..03c3707919b
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginInstallerTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.batch.bootstrap;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.core.plugins.RemotePlugin;
+import org.sonar.home.cache.FileCache;
+
+import java.io.File;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class BatchPluginInstallerTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ FileCache fileCache = mock(FileCache.class);
+ BatchPluginPredicate pluginPredicate = mock(BatchPluginPredicate.class);
+
+ @Test
+ public void listRemotePlugins() {
+
+ ServerClient server = mock(ServerClient.class);
+ when(server.request("/deploy/plugins/index.txt")).thenReturn("checkstyle,false\nsqale,false");
+ BatchPluginInstaller installer = new BatchPluginInstaller(server, fileCache, pluginPredicate);
+
+ List remotePlugins = installer.listRemotePlugins();
+ assertThat(remotePlugins).extracting("key").containsOnly("checkstyle", "sqale");
+ }
+
+ @Test
+ public void should_download_plugin() throws Exception {
+ File pluginJar = temp.newFile();
+ when(fileCache.get(eq("checkstyle-plugin.jar"), eq("fakemd5_1"), any(FileCache.Downloader.class))).thenReturn(pluginJar);
+
+ ServerClient server = mock(ServerClient.class);
+ BatchPluginInstaller installer = new BatchPluginInstaller(server, fileCache, pluginPredicate);
+
+ RemotePlugin remote = new RemotePlugin("checkstyle", true).setFile("checkstyle-plugin.jar", "fakemd5_1");
+ File file = installer.download(remote);
+
+ assertThat(file).isEqualTo(pluginJar);
+ }
+
+ @Test
+ public void should_fail_to_get_plugin_index() {
+ thrown.expect(IllegalStateException.class);
+
+ ServerClient server = mock(ServerClient.class);
+ doThrow(new IllegalStateException()).when(server).request("/deploy/plugins/index.txt");
+
+ new BatchPluginInstaller(server, fileCache, pluginPredicate).installRemotes();
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginJarInstallerTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginJarInstallerTest.java
deleted file mode 100644
index 2209c57431a..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginJarInstallerTest.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.batch.bootstrap;
-
-import org.apache.commons.io.FileUtils;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.core.plugins.DefaultPluginMetadata;
-import org.sonar.home.cache.FileCacheBuilder;
-
-import java.io.File;
-import java.io.IOException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class BatchPluginJarInstallerTest {
-
- private BatchPluginJarInstaller extractor;
-
- @ClassRule
- public static TemporaryFolder temporaryFolder = new TemporaryFolder();
-
- private File userHome;
-
- @Before
- public void setUp() throws IOException {
- userHome = temporaryFolder.newFolder();
- extractor = new BatchPluginJarInstaller(new FileCacheBuilder().setUserHome(userHome).build());
- }
-
- @Test
- public void should_copy_and_extract_dependencies() throws IOException {
- File fileFromCache = getFileFromCache("sonar-checkstyle-plugin-2.8.jar");
- DefaultPluginMetadata metadata = extractor.installToCache(fileFromCache, true);
-
- assertThat(metadata.getKey()).isEqualTo("checkstyle");
- assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar")).exists();
- assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar_unzip/META-INF/lib/checkstyle-5.1.jar")).exists();
- }
-
- @Test
- public void should_extract_only_dependencies() throws IOException {
- File fileFromCache = getFileFromCache("sonar-checkstyle-plugin-2.8.jar");
- extractor.installToCache(fileFromCache, true);
-
- assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar")).exists();
- assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar_unzip/META-INF/MANIFEST.MF")).doesNotExist();
- assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar_unzip/org/sonar/plugins/checkstyle/CheckstyleVersion.class")).doesNotExist();
- }
-
- File getFileFromCache(String filename) throws IOException {
- File src = FileUtils.toFile(BatchPluginJarInstallerTest.class.getResource("/org/sonar/batch/bootstrap/BatchPluginJarInstallerTest/" + filename));
- File destFile = new File(new File(userHome, "" + filename.hashCode()), filename);
- FileUtils.copyFile(src, destFile);
- return destFile;
- }
-
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginPredicateTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginPredicateTest.java
new file mode 100644
index 00000000000..9dcebd6d07f
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginPredicateTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.batch.bootstrap;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.home.cache.FileCache;
+import org.sonar.home.cache.FileCacheBuilder;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class BatchPluginPredicateTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ DefaultAnalysisMode mode = mock(DefaultAnalysisMode.class);
+ FileCache cache;
+ File userHome;
+
+ @Before
+ public void before() throws IOException {
+ userHome = temp.newFolder();
+ cache = new FileCacheBuilder().setUserHome(userHome).build();
+ }
+
+ @Test
+ public void shouldAlwaysAcceptIfNoWhiteListAndBlackList() {
+ BatchPluginPredicate predicate = new BatchPluginPredicate(new Settings(), mode);
+ assertThat(predicate.apply("pmd")).isTrue();
+ assertThat(predicate.apply("buildbreaker")).isTrue();
+ }
+
+ @Test
+ public void shouldBlackListBuildBreakerInPreviewMode() {
+ when(mode.isPreview()).thenReturn(true);
+ BatchPluginPredicate predicate = new BatchPluginPredicate(new Settings(), mode);
+ assertThat(predicate.apply("buildbreaker")).isFalse();
+ }
+
+ @Test
+ public void whiteListShouldTakePrecedenceOverBlackList() {
+ Settings settings = new Settings()
+ .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs")
+ .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura,pmd");
+ BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode);
+ assertThat(predicate.apply("pmd")).isTrue();
+ }
+
+ @Test
+ public void corePluginShouldAlwaysBeInWhiteList() {
+ Settings settings = new Settings()
+ .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
+ BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode);
+ assertThat(predicate.apply("core")).isTrue();
+ }
+
+ @Test
+ public void corePluginShouldNeverBeInBlackList() {
+ Settings settings = new Settings()
+ .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "core,findbugs");
+ BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode);
+ assertThat(predicate.apply("core")).isTrue();
+ }
+
+ @Test
+ public void check_white_list_with_black_list() {
+ Settings settings = new Settings()
+ .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs")
+ .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura");
+ BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode);
+ assertThat(predicate.apply("checkstyle")).isTrue();
+ assertThat(predicate.apply("pmd")).isTrue();
+ assertThat(predicate.apply("cobertura")).isFalse();
+ }
+
+ @Test
+ public void check_white_list_when_plugin_is_in_both_list() {
+ Settings settings = new Settings()
+ .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "cobertura,checkstyle,pmd,findbugs")
+ .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura");
+ BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode);
+ assertThat(predicate.apply("checkstyle")).isTrue();
+ assertThat(predicate.apply("pmd")).isTrue();
+ assertThat(predicate.apply("cobertura")).isTrue();
+ }
+
+ @Test
+ public void check_black_list_if_no_white_list() {
+ Settings settings = new Settings()
+ .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
+ BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode);
+ assertThat(predicate.apply("checkstyle")).isFalse();
+ assertThat(predicate.apply("pmd")).isFalse();
+ assertThat(predicate.apply("cobertura")).isTrue();
+ }
+
+ @Test
+ public void should_concatenate_preview_predicates() {
+ Settings settings = new Settings()
+ .setProperty(CoreProperties.PREVIEW_INCLUDE_PLUGINS, "cockpit")
+ .setProperty(CoreProperties.PREVIEW_EXCLUDE_PLUGINS, "views")
+ .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd");
+ when(mode.isPreview()).thenReturn(true);
+ BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode);
+ assertThat(predicate.getWhites()).containsOnly("cockpit");
+ assertThat(predicate.getBlacks()).containsOnly("views", "checkstyle", "pmd");
+ }
+
+ @Test
+ public void should_concatenate_deprecated_dry_run_predicates() {
+ Settings settings = new Settings()
+ .setProperty(CoreProperties.DRY_RUN_INCLUDE_PLUGINS, "cockpit")
+ .setProperty(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, "views")
+ .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd");
+ when(mode.isPreview()).thenReturn(true);
+ BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode);
+ assertThat(predicate.getWhites()).containsOnly("cockpit");
+ assertThat(predicate.getBlacks()).containsOnly("views", "checkstyle", "pmd");
+ }
+
+ @Test
+ public void inclusions_and_exclusions_should_be_trimmed() {
+ Settings settings = new Settings()
+ .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle, pmd, findbugs")
+ .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura, pmd");
+ BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode);
+ assertThat(predicate.apply("pmd")).isTrue();
+ }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java
index 66a499b01c0..7c82edbb64f 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java
@@ -17,219 +17,237 @@
* 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.batch.bootstrap;
-
-import com.google.common.io.Resources;
-import org.apache.commons.io.FileUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.Settings;
-import org.sonar.core.plugins.RemotePlugin;
-import org.sonar.home.cache.FileCache;
-import org.sonar.home.cache.FileCacheBuilder;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class BatchPluginRepositoryTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- private BatchPluginRepository repository;
- private DefaultAnalysisMode mode;
- private FileCache cache;
- private File userHome;
-
- @Before
- public void before() throws IOException {
- mode = mock(DefaultAnalysisMode.class);
- when(mode.isPreview()).thenReturn(false);
- userHome = temp.newFolder();
- cache = new FileCacheBuilder().setUserHome(userHome).build();
- }
-
- @After
- public void tearDown() {
- if (repository != null) {
- repository.stop();
- }
- }
-
- @Test
- public void shouldLoadPlugin() throws Exception {
- RemotePlugin checkstyle = new RemotePlugin("checkstyle", true);
-
- DefaultPluginsRepository downloader = mock(DefaultPluginsRepository.class);
- when(downloader.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar"));
-
- repository = new BatchPluginRepository(downloader, new Settings(), mode, new BatchPluginJarInstaller(cache));
-
- repository.doStart(Arrays.asList(checkstyle));
-
- assertThat(repository.getPlugin("checkstyle")).isNotNull();
- assertThat(repository.getMetadata()).hasSize(1);
- assertThat(repository.getMetadata("checkstyle").getName()).isEqualTo("Checkstyle");
- assertThat(repository.getMetadata("checkstyle").getDeployedFiles()).hasSize(4); // plugin + 3 dependencies
- }
-
- @Test
- public void shouldLoadPluginExtension() throws Exception {
- RemotePlugin checkstyle = new RemotePlugin("checkstyle", true);
- RemotePlugin checkstyleExt = new RemotePlugin("checkstyleextensions", false);
-
- DefaultPluginsRepository downloader = mock(DefaultPluginsRepository.class);
- when(downloader.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar"));
- when(downloader.pluginFile(checkstyleExt)).thenReturn(fileFromCache("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar"));
-
- repository = new BatchPluginRepository(downloader, new Settings(), mode, new BatchPluginJarInstaller(cache));
-
- repository.doStart(Arrays.asList(checkstyle, checkstyleExt));
-
- assertThat(repository.getPlugin("checkstyle")).isNotNull();
- assertThat(repository.getPlugin("checkstyleextensions")).isNotNull();
- assertThat(repository.getMetadata()).hasSize(2);
- assertThat(repository.getMetadata("checkstyle").getName()).isEqualTo("Checkstyle");
- assertThat(repository.getMetadata("checkstyleextensions").getVersion()).isEqualTo("0.1-SNAPSHOT");
- }
-
- @Test
- public void shouldExcludePluginAndItsExtensions() throws Exception {
- RemotePlugin checkstyle = new RemotePlugin("checkstyle", true);
- RemotePlugin checkstyleExt = new RemotePlugin("checkstyleextensions", false);
-
- DefaultPluginsRepository downloader = mock(DefaultPluginsRepository.class);
- when(downloader.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar"));
- when(downloader.pluginFile(checkstyleExt)).thenReturn(fileFromCache("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar"));
-
- Settings settings = new Settings();
- settings.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle");
- repository = new BatchPluginRepository(downloader, settings, mode, new BatchPluginJarInstaller(cache));
-
- repository.doStart(Arrays.asList(checkstyle, checkstyleExt));
-
- assertThat(repository.getMetadata()).isEmpty();
- }
-
- private File fileFromCache(String filename) throws Exception {
- File file = new File(Resources.getResource("org/sonar/batch/bootstrap/BatchPluginRepositoryTest/" + filename).toURI());
- File destDir = new File(userHome, "cache/foomd5");
- FileUtils.forceMkdir(destDir);
- FileUtils.copyFileToDirectory(file, destDir);
- return new File(destDir, filename);
- }
-
- @Test
- public void shouldAlwaysAcceptIfNoWhiteListAndBlackList() {
- BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(new Settings(), mode);
- assertThat(filter.accepts("pmd")).isTrue();
- assertThat(filter.accepts("buildbreaker")).isTrue();
- }
-
- @Test
- public void shouldBlackListBuildBreakerInPreviewMode() {
- when(mode.isPreview()).thenReturn(true);
- BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(new Settings(), mode);
- assertThat(filter.accepts("buildbreaker")).isFalse();
- }
-
- @Test
- public void whiteListShouldTakePrecedenceOverBlackList() {
- Settings settings = new Settings()
- .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs")
- .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura,pmd");
- BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
- assertThat(filter.accepts("pmd")).isTrue();
- }
-
- @Test
- public void corePluginShouldAlwaysBeInWhiteList() {
- Settings settings = new Settings()
- .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
- BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
- assertThat(filter.accepts("core")).isTrue();
- }
-
- @Test
- public void corePluginShouldNeverBeInBlackList() {
- Settings settings = new Settings()
- .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "core,findbugs");
- BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
- assertThat(filter.accepts("core")).isTrue();
- }
-
- @Test
- public void check_white_list_with_black_list() {
- Settings settings = new Settings()
- .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs")
- .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura");
- BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
- assertThat(filter.accepts("checkstyle")).isTrue();
- assertThat(filter.accepts("pmd")).isTrue();
- assertThat(filter.accepts("cobertura")).isFalse();
- }
-
- @Test
- public void check_white_list_when_plugin_is_in_both_list() {
- Settings settings = new Settings()
- .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "cobertura,checkstyle,pmd,findbugs")
- .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura");
- BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
- assertThat(filter.accepts("checkstyle")).isTrue();
- assertThat(filter.accepts("pmd")).isTrue();
- assertThat(filter.accepts("cobertura")).isTrue();
- }
-
- @Test
- public void check_black_list_if_no_white_list() {
- Settings settings = new Settings()
- .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
- BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
- assertThat(filter.accepts("checkstyle")).isFalse();
- assertThat(filter.accepts("pmd")).isFalse();
- assertThat(filter.accepts("cobertura")).isTrue();
- }
-
- @Test
- public void should_concatenate_preview_filters() {
- Settings settings = new Settings()
- .setProperty(CoreProperties.PREVIEW_INCLUDE_PLUGINS, "cockpit")
- .setProperty(CoreProperties.PREVIEW_EXCLUDE_PLUGINS, "views")
- .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd");
- when(mode.isPreview()).thenReturn(true);
- BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
- assertThat(filter.whites).containsOnly("cockpit");
- assertThat(filter.blacks).containsOnly("views", "checkstyle", "pmd");
- }
-
- @Test
- public void should_concatenate_deprecated_dry_run_filters() {
- Settings settings = new Settings()
- .setProperty(CoreProperties.DRY_RUN_INCLUDE_PLUGINS, "cockpit")
- .setProperty(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, "views")
- .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd");
- when(mode.isPreview()).thenReturn(true);
- BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
- assertThat(filter.whites).containsOnly("cockpit");
- assertThat(filter.blacks).containsOnly("views", "checkstyle", "pmd");
- }
-
- @Test
- public void inclusions_and_exclusions_should_be_trimmed() {
- Settings settings = new Settings()
- .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle, pmd, findbugs")
- .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura, pmd");
- BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
- assertThat(filter.accepts("pmd")).isTrue();
- }
-
-}
+///*
+// * 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.batch.bootstrap;
+//
+//import com.google.common.io.Resources;
+//import org.apache.commons.io.FileUtils;
+//import org.junit.After;
+//import org.junit.Before;
+//import org.junit.Rule;
+//import org.junit.Test;
+//import org.junit.rules.TemporaryFolder;
+//import org.sonar.api.CoreProperties;
+//import org.sonar.api.config.Settings;
+//import org.sonar.core.plugins.RemotePlugin;
+//import org.sonar.home.cache.FileCache;
+//import org.sonar.home.cache.FileCacheBuilder;
+//
+//import java.io.File;
+//import java.io.IOException;
+//import java.util.Arrays;
+//
+//import static org.mockito.Mockito.mock;
+//import static org.mockito.Mockito.when;
+//
+//public class BatchPluginRepositoryTest {
+//
+// @Rule
+// public TemporaryFolder temp = new TemporaryFolder();
+//
+// private BatchPluginRepository repository;
+// private DefaultAnalysisMode mode;
+// private FileCache cache;
+// private File userHome;
+//
+// @Before
+// public void before() throws IOException {
+// mode = mock(DefaultAnalysisMode.class);
+// when(mode.isPreview()).thenReturn(false);
+// userHome = temp.newFolder();
+// cache = new FileCacheBuilder().setUserHome(userHome).build();
+// }
+//
+// @After
+// public void tearDown() {
+// if (repository != null) {
+// repository.stop();
+// }
+// }
+//
+// @Test
+// public void shouldLoadPlugin() throws Exception {
+// RemotePlugin checkstyle = new RemotePlugin("checkstyle", true);
+//
+// DefaultPluginRepository installer = mock(DefaultPluginsRepository.class);
+// when(installer.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar"));
+//
+// repository = new BatchPluginRepository(installer, new Settings(), mode, new BatchPluginJarInstaller(cache));
+//
+// repository.doStart(Arrays.asList(checkstyle));
+//
+// assertThat(repository.getPlugin("checkstyle")).isNotNull();
+// assertThat(repository.getMetadata()).hasSize(1);
+// assertThat(repository.getMetadata("checkstyle").getName()).isEqualTo("Checkstyle");
+// assertThat(repository.getMetadata("checkstyle").getDeployedFiles()).hasSize(4); // plugin + 3 dependencies
+// }
+//
+// @Test
+// public void shouldLoadPluginExtension() throws Exception {
+// RemotePlugin checkstyle = new RemotePlugin("checkstyle", true);
+// RemotePlugin checkstyleExt = new RemotePlugin("checkstyleextensions", false);
+//
+// DefaultPluginsRepository downloader = mock(DefaultPluginsRepository.class);
+// when(downloader.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar"));
+// when(downloader.pluginFile(checkstyleExt)).thenReturn(fileFromCache("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar"));
+//
+// repository = new BatchPluginRepository(downloader, new Settings(), mode, new BatchPluginJarInstaller(cache));
+//
+// repository.doStart(Arrays.asList(checkstyle, checkstyleExt));
+//
+// assertThat(repository.getPlugin("checkstyle")).isNotNull();
+// assertThat(repository.getPlugin("checkstyleextensions")).isNotNull();
+// assertThat(repository.getMetadata()).hasSize(2);
+// assertThat(repository.getMetadata("checkstyle").getName()).isEqualTo("Checkstyle");
+// assertThat(repository.getMetadata("checkstyleextensions").getVersion()).isEqualTo("0.1-SNAPSHOT");
+// }
+//
+// @Test
+// public void shouldExcludePluginAndItsExtensions() throws Exception {
+// RemotePlugin checkstyle = new RemotePlugin("checkstyle", true);
+// RemotePlugin checkstyleExt = new RemotePlugin("checkstyleextensions", false);
+//
+// DefaultPluginsRepository downloader = mock(DefaultPluginsRepository.class);
+// when(downloader.pluginFile(checkstyle)).thenReturn(fileFromCache("sonar-checkstyle-plugin-2.8.jar"));
+// when(downloader.pluginFile(checkstyleExt)).thenReturn(fileFromCache("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar"));
+//
+// Settings settings = new Settings();
+// settings.setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle");
+// repository = new BatchPluginRepository(downloader, settings, mode, new BatchPluginJarInstaller(cache));
+//
+// repository.doStart(Arrays.asList(checkstyle, checkstyleExt));
+//
+// assertThat(repository.getMetadata()).isEmpty();
+// }
+//
+// private File fileFromCache(String filename) throws Exception {
+// File file = new File(Resources.getResource("org/sonar/batch/bootstrap/BatchPluginRepositoryTest/" + filename).toURI());
+// File destDir = new File(userHome, "cache/foomd5");
+// FileUtils.forceMkdir(destDir);
+// FileUtils.copyFileToDirectory(file, destDir);
+// return new File(destDir, filename);
+// }
+//
+// @Test
+// public void shouldAlwaysAcceptIfNoWhiteListAndBlackList() {
+// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(new Settings(), mode);
+// assertThat(filter.accepts("pmd")).isTrue();
+// assertThat(filter.accepts("buildbreaker")).isTrue();
+// }
+//
+// @Test
+// public void shouldBlackListBuildBreakerInPreviewMode() {
+// when(mode.isPreview()).thenReturn(true);
+// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(new Settings(), mode);
+// assertThat(filter.accepts("buildbreaker")).isFalse();
+// }
+//
+// @Test
+// public void whiteListShouldTakePrecedenceOverBlackList() {
+// Settings settings = new Settings()
+// .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs")
+// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura,pmd");
+// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
+// assertThat(filter.accepts("pmd")).isTrue();
+// }
+//
+// @Test
+// public void corePluginShouldAlwaysBeInWhiteList() {
+// Settings settings = new Settings()
+// .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
+// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
+// assertThat(filter.accepts("core")).isTrue();
+// }
+//
+// @Test
+// public void corePluginShouldNeverBeInBlackList() {
+// Settings settings = new Settings()
+// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "core,findbugs");
+// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
+// assertThat(filter.accepts("core")).isTrue();
+// }
+//
+// @Test
+// public void check_white_list_with_black_list() {
+// Settings settings = new Settings()
+// .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs")
+// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura");
+// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
+// assertThat(filter.accepts("checkstyle")).isTrue();
+// assertThat(filter.accepts("pmd")).isTrue();
+// assertThat(filter.accepts("cobertura")).isFalse();
+// }
+//
+// @Test
+// public void check_white_list_when_plugin_is_in_both_list() {
+// Settings settings = new Settings()
+// .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "cobertura,checkstyle,pmd,findbugs")
+// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura");
+// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
+// assertThat(filter.accepts("checkstyle")).isTrue();
+// assertThat(filter.accepts("pmd")).isTrue();
+// assertThat(filter.accepts("cobertura")).isTrue();
+// }
+//
+// @Test
+// public void check_black_list_if_no_white_list() {
+// Settings settings = new Settings()
+// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
+// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
+// assertThat(filter.accepts("checkstyle")).isFalse();
+// assertThat(filter.accepts("pmd")).isFalse();
+// assertThat(filter.accepts("cobertura")).isTrue();
+// }
+//
+// @Test
+// public void should_concatenate_preview_filters() {
+// Settings settings = new Settings()
+// .setProperty(CoreProperties.PREVIEW_INCLUDE_PLUGINS, "cockpit")
+// .setProperty(CoreProperties.PREVIEW_EXCLUDE_PLUGINS, "views")
+// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd");
+// when(mode.isPreview()).thenReturn(true);
+// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
+// assertThat(filter.whites).containsOnly("cockpit");
+// assertThat(filter.blacks).containsOnly("views", "checkstyle", "pmd");
+// }
+//
+// @Test
+// public void should_concatenate_deprecated_dry_run_filters() {
+// Settings settings = new Settings()
+// .setProperty(CoreProperties.DRY_RUN_INCLUDE_PLUGINS, "cockpit")
+// .setProperty(CoreProperties.DRY_RUN_EXCLUDE_PLUGINS, "views")
+// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "checkstyle,pmd");
+// when(mode.isPreview()).thenReturn(true);
+// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
+// assertThat(filter.whites).containsOnly("cockpit");
+// assertThat(filter.blacks).containsOnly("views", "checkstyle", "pmd");
+// }
+//
+// @Test
+// public void inclusions_and_exclusions_should_be_trimmed() {
+// Settings settings = new Settings()
+// .setProperty(CoreProperties.BATCH_INCLUDE_PLUGINS, "checkstyle, pmd, findbugs")
+// .setProperty(CoreProperties.BATCH_EXCLUDE_PLUGINS, "cobertura, pmd");
+// BatchPluginRepository.PluginFilter filter = new BatchPluginRepository.PluginFilter(settings, mode);
+// assertThat(filter.accepts("pmd")).isTrue();
+// }
+//
+//}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginUnzipperTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginUnzipperTest.java
new file mode 100644
index 00000000000..06a25148775
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginUnzipperTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.batch.bootstrap;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.UnzippedPlugin;
+import org.sonar.home.cache.FileCache;
+import org.sonar.home.cache.FileCacheBuilder;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class BatchPluginUnzipperTest {
+
+ @ClassRule
+ public static TemporaryFolder temp = new TemporaryFolder();
+
+ File userHome;
+ BatchPluginUnzipper underTest;
+
+ @Before
+ public void setUp() throws IOException {
+ userHome = temp.newFolder();
+ FileCache fileCache = new FileCacheBuilder().setUserHome(userHome).build();
+ underTest = new BatchPluginUnzipper(fileCache);
+ }
+
+ @Test
+ public void copy_and_extract_libs() throws IOException {
+ File fileFromCache = getFileFromCache("sonar-checkstyle-plugin-2.8.jar");
+ UnzippedPlugin unzipped = underTest.unzip(PluginInfo.create(fileFromCache));
+
+ assertThat(unzipped.getKey()).isEqualTo("checkstyle");
+ assertThat(unzipped.getMain()).isFile().exists();
+ assertThat(unzipped.getLibs()).extracting("name").containsOnly("antlr-2.7.6.jar", "checkstyle-5.1.jar", "commons-cli-1.0.jar");
+ assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar")).exists();
+ assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar_unzip/META-INF/lib/checkstyle-5.1.jar")).exists();
+ }
+
+ @Test
+ public void extract_only_libs() throws IOException {
+ File fileFromCache = getFileFromCache("sonar-checkstyle-plugin-2.8.jar");
+ underTest.unzip(PluginInfo.create(fileFromCache));
+
+ assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar")).exists();
+ assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar_unzip/META-INF/MANIFEST.MF")).doesNotExist();
+ assertThat(new File(fileFromCache.getParent(), "sonar-checkstyle-plugin-2.8.jar_unzip/org/sonar/plugins/checkstyle/CheckstyleVersion.class")).doesNotExist();
+ }
+
+ File getFileFromCache(String filename) throws IOException {
+ File src = FileUtils.toFile(BatchPluginUnzipperTest.class.getResource("/org/sonar/batch/bootstrap/BatchPluginUnzipperTest/" + filename));
+ File destFile = new File(new File(userHome, "" + filename.hashCode()), filename);
+ FileUtils.copyFile(src, destFile);
+ return destFile;
+ }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DefaultPluginsRepositoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DefaultPluginsRepositoryTest.java
deleted file mode 100644
index 57e940ab7ae..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DefaultPluginsRepositoryTest.java
+++ /dev/null
@@ -1,88 +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.batch.bootstrap;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.core.plugins.RemotePlugin;
-import org.sonar.home.cache.FileCache;
-
-import java.io.File;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class DefaultPluginsRepositoryTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- @Test
- public void should_request_list_of_plugins() {
- FileCache cache = mock(FileCache.class);
- ServerClient server = mock(ServerClient.class);
- when(server.request("/deploy/plugins/index.txt")).thenReturn("checkstyle,true\nsqale,false");
- DefaultPluginsRepository downloader = new DefaultPluginsRepository(cache, server);
-
- List plugins = downloader.pluginList();
- assertThat(plugins).hasSize(2);
- assertThat(plugins.get(0).getKey()).isEqualTo("checkstyle");
- assertThat(plugins.get(0).isCore()).isTrue();
- assertThat(plugins.get(1).getKey()).isEqualTo("sqale");
- assertThat(plugins.get(1).isCore()).isFalse();
- }
-
- @Test
- public void should_download_plugin() throws Exception {
- FileCache cache = mock(FileCache.class);
-
- File pluginJar = temp.newFile();
- when(cache.get(eq("checkstyle-plugin.jar"), eq("fakemd5_1"), any(FileCache.Downloader.class))).thenReturn(pluginJar);
-
- ServerClient server = mock(ServerClient.class);
- DefaultPluginsRepository downloader = new DefaultPluginsRepository(cache, server);
-
- RemotePlugin plugin = new RemotePlugin("checkstyle", true)
- .setFile("checkstyle-plugin.jar", "fakemd5_1");
- File file = downloader.pluginFile(plugin);
-
- assertThat(file).isEqualTo(pluginJar);
- }
-
- @Test
- public void should_fail_to_get_plugin_index() {
- thrown.expect(IllegalStateException.class);
-
- ServerClient server = mock(ServerClient.class);
- doThrow(new IllegalStateException()).when(server).request("/deploy/plugins/index.txt");
-
- new DefaultPluginsRepository(mock(FileCache.class), server).pluginList();
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java
index 0647b0e22ec..b01040b29cd 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ExtensionInstallerTest.java
@@ -19,7 +19,6 @@
*/
package org.sonar.batch.bootstrap;
-import com.google.common.collect.Maps;
import org.apache.commons.lang.ClassUtils;
import org.junit.Before;
import org.junit.Test;
@@ -28,13 +27,12 @@ import org.sonar.api.ExtensionProvider;
import org.sonar.api.Plugin;
import org.sonar.api.SonarPlugin;
import org.sonar.api.batch.SupportedEnvironment;
-import org.sonar.api.platform.ComponentContainer;
-import org.sonar.api.platform.PluginMetadata;
import org.sonar.batch.bootstrapper.EnvironmentInformation;
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.core.platform.PluginInfo;
import java.util.Arrays;
import java.util.List;
-import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@@ -42,19 +40,15 @@ import static org.mockito.Mockito.when;
public class ExtensionInstallerTest {
- private DefaultAnalysisMode mode;
- PluginMetadata metadata = mock(PluginMetadata.class);
+ DefaultAnalysisMode mode;
+ BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class);
- Map newPlugin(final Object... extensions) {
- Map result = Maps.newHashMap();
- result.put(metadata,
- new SonarPlugin() {
- public List getExtensions() {
- return Arrays.asList(extensions);
- }
+ private static Plugin newPluginInstance(final Object... extensions) {
+ return new SonarPlugin() {
+ public List getExtensions() {
+ return Arrays.asList(extensions);
}
- );
- return result;
+ };
}
@Before
@@ -64,8 +58,9 @@ public class ExtensionInstallerTest {
@Test
public void should_filter_extensions_to_install() {
- BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class);
- when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(Foo.class, Bar.class));
+ when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo")));
+ when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(Foo.class, Bar.class));
+
ComponentContainer container = new ComponentContainer();
ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode);
installer.install(container, new FooMatcher());
@@ -76,8 +71,8 @@ public class ExtensionInstallerTest {
@Test
public void should_execute_extension_provider() {
- BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class);
- when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(new FooProvider(), new BarProvider()));
+ when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo")));
+ when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(new FooProvider(), new BarProvider()));
ComponentContainer container = new ComponentContainer();
ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode);
@@ -89,8 +84,8 @@ public class ExtensionInstallerTest {
@Test
public void should_provide_list_of_extensions() {
- BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class);
- when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(new FooBarProvider()));
+ when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo")));
+ when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(new FooBarProvider()));
ComponentContainer container = new ComponentContainer();
ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode);
@@ -102,9 +97,8 @@ public class ExtensionInstallerTest {
@Test
public void should_not_install_on_unsupported_environment() {
- BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class);
- when(pluginRepository.getPluginsByMetadata()).thenReturn(newPlugin(Foo.class, MavenExtension.class, AntExtension.class, new BarProvider()));
-
+ when(pluginRepository.getPluginInfos()).thenReturn(Arrays.asList(new PluginInfo("foo")));
+ when(pluginRepository.getPluginInstance("foo")).thenReturn(newPluginInstance(Foo.class, MavenExtension.class, AntExtension.class, new BarProvider()));
ComponentContainer container = new ComponentContainer();
ExtensionInstaller installer = new ExtensionInstaller(pluginRepository, new EnvironmentInformation("ant", "1.7"), mode);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalContainerTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalContainerTest.java
index 9fce2c7a951..ac87c52fa51 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalContainerTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/GlobalContainerTest.java
@@ -19,25 +19,15 @@
*/
package org.sonar.batch.bootstrap;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.junit.Test;
import org.sonar.api.BatchExtension;
-import org.sonar.api.Plugin;
-import org.sonar.api.SonarPlugin;
-import org.sonar.api.platform.PluginMetadata;
import org.sonar.api.utils.TempFolder;
import org.sonar.core.config.Logback;
-import java.util.Arrays;
import java.util.Collections;
-import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
public class GlobalContainerTest {
@Test
@@ -58,22 +48,6 @@ public class GlobalContainerTest {
assertThat(container.getComponentByType(Bar.class)).isNotNull();
}
- @Test
- public void should_install_plugins() {
- PluginMetadata metadata = mock(PluginMetadata.class);
- FakePlugin plugin = new FakePlugin();
- BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class);
- when(pluginRepository.getPluginsByMetadata()).thenReturn(ImmutableMap.of(
- metadata, plugin
- ));
-
- GlobalContainer container = spy(GlobalContainer.create(Collections.emptyMap(), Lists.