summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/pom.xml12
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/ComputationContainer.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrator.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/debt/DebtModelPluginRepository.java22
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java25
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/Platform.java11
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/RailsAppsDeployer.java32
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java12
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java26
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/InstalledPluginReferentialFactory.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java24
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/PluginReferentialMetadataConverter.java22
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ServerExtensionInstaller.java43
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginJarInstaller.java62
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginJarsInstaller.java286
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java355
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ServerPluginUnzipper.java65
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/StaticResourcesServlet.java14
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ws/CancelAllPluginsWsAction.java10
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledPluginsWsAction.java25
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java29
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginWSCommons.java28
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/plugins/ws/UninstallPluginsWsAction.java34
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/IndexQueue.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/startup/GeneratePluginIndex.java15
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java39
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/debt/DebtModelPluginRepositoryTest.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/es/EsTester.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/DefaultServerFileSystemTest.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/RailsAppsDeployerTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java60
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/InstalledPluginReferentialFactoryTest.java26
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/MimeTypesTest.java6
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java31
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/PluginReferentialMetadataConverterTest.java18
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginJarsInstallerTest.java309
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java297
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginUnzipperTest.java64
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/TestProjectUtils.java (renamed from server/sonar-server/src/test/java/org/sonar/server/platform/SonarHomeTest.java)21
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/ws/CancelAllPluginsWsActionTest.java8
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledPluginsWsActionTest.java48
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java30
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PluginWSCommonsTest.java13
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/plugins/ws/UninstallPluginsWsActionTest.java21
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/startup/GeneratePluginIndexTest.java23
-rw-r--r--server/sonar-server/src/test/projects/.gitignore7
-rw-r--r--server/sonar-server/src/test/projects/README.txt3
-rw-r--r--server/sonar-server/src/test/projects/pom.xml19
-rw-r--r--server/sonar-server/src/test/projects/test-base-plugin-v2/pom.xml36
-rw-r--r--server/sonar-server/src/test/projects/test-base-plugin-v2/src/BasePlugin.java11
-rw-r--r--server/sonar-server/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jarbin0 -> 2437 bytes
-rw-r--r--server/sonar-server/src/test/projects/test-base-plugin/pom.xml36
-rw-r--r--server/sonar-server/src/test/projects/test-base-plugin/src/BasePlugin.java11
-rw-r--r--server/sonar-server/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jarbin0 -> 2437 bytes
-rw-r--r--server/sonar-server/src/test/projects/test-core-plugin/pom.xml36
-rw-r--r--server/sonar-server/src/test/projects/test-core-plugin/src/CorePlugin.java11
-rw-r--r--server/sonar-server/src/test/projects/test-core-plugin/target/test-core-plugin-0.1-SNAPSHOT.jarbin0 -> 2412 bytes
-rw-r--r--server/sonar-server/src/test/projects/test-extend-plugin/pom.xml37
-rw-r--r--server/sonar-server/src/test/projects/test-extend-plugin/src/ExtendPlugin.java11
-rw-r--r--server/sonar-server/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jarbin0 -> 2481 bytes
-rw-r--r--server/sonar-server/src/test/projects/test-libs-plugin/pom.xml49
-rw-r--r--server/sonar-server/src/test/projects/test-libs-plugin/src/LibsPlugin.java11
-rw-r--r--server/sonar-server/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jarbin0 -> 40097 bytes
-rw-r--r--server/sonar-server/src/test/projects/test-require-plugin/pom.xml37
-rw-r--r--server/sonar-server/src/test/projects/test-require-plugin/src/RequirePlugin.java11
-rw-r--r--server/sonar-server/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jarbin0 -> 2488 bytes
-rw-r--r--server/sonar-server/src/test/projects/test-requirenew-plugin/pom.xml37
-rw-r--r--server/sonar-server/src/test/projects/test-requirenew-plugin/src/RequirePlugin.java11
-rw-r--r--server/sonar-server/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jarbin0 -> 2553 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/extension.jarbin885 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/foo-plugin.jarbin1460 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/sonar-build-breaker-plugin-0.1.jarbin5027 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginDownloaderTest/foo-plugin-1.0.jarbin955 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginExtensionMetadataTest/version1/extension.jarbin885 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginExtensionMetadataTest/version2/extension.jarbin898 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/foo-plugin-1.0.jarbin1076 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/foo-plugin-2.0.jarbin1077 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/not-a-plugin.jarbin960 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/old-plugin.jarbin980 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataTest/foo-plugin.jarbin1460 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/bar-plugin-1.0.jarbin714 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/foo-plugin-1.0.jarbin955 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/foo-plugin-2.0.jarbin901 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/not-a-plugin.jarbin396 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/require-sq-2.5.jarbin12689 -> 0 bytes
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jarbin7456 -> 0 bytes
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/updatecenter_controller.rb6
87 files changed, 1462 insertions, 1134 deletions
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 @@
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
+
</resources>
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <filtering>false</filtering>
+ </testResource>
+ <testResource>
+ <directory>src/test/projects</directory>
+ <filtering>false</filtering>
+ </testResource>
+
+ </testResources>
<plugins>
<plugin>
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 "<pluginKey>-model.xml".
* </p>
*/
-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<File> getCorePlugins() {
- File corePluginsDir = new File(getHomeDir(), "lib/core-plugins");
- return getFiles(corePluginsDir, "jar");
- }
-
- public List<File> getBundledPlugins() {
- File corePluginsDir = new File(getHomeDir(), "lib/bundled-plugins");
- return getFiles(corePluginsDir, "jar");
+ public File getInstalledPluginsDir() {
+ return new File(getHomeDir(), "extensions/plugins");
}
- public List<File> 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<File> getFiles(File dir, String... fileSuffixes) {
- List<File> files = new ArrayList<File>();
+ List<File> 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<String, String>() {
@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<String, Object> attributes() {
LinkedHashMap<String, Object> attributes = new LinkedHashMap<>();
- for (PluginMetadata plugin : plugins()) {
+ for (PluginInfo plugin : plugins()) {
LinkedHashMap<String, Object> 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<PluginMetadata> plugins() {
- return Lists.newArrayList(Iterables.filter(repository.getMetadata(), new Predicate<PluginMetadata>() {
+ private Iterable<PluginInfo> plugins() {
+ return Iterables.filter(repository.getPluginInfos(), new Predicate<PluginInfo>() {
@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<DefaultPluginMetadata> getDownloadedPlugins() {
- return newArrayList(transform(listPlugins(this.downloadDir), installer.fileToPlugin()));
+ public Collection<PluginInfo> 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<File> listTempFile(File dir) {
- return FileUtils.listFiles(dir, new String[]{TMP_SUFFIX}, false);
+ return FileUtils.listFiles(dir, new String[] {TMP_SUFFIX}, false);
}
private static Collection<File> 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<PluginMetadata> metadata) {
+ public static PluginReferential getInstalledPluginReferential(Collection<PluginInfo> metadata) {
List<PluginManifest> pluginManifestList = getPluginManifestList(metadata);
return PluginReferentialManifestConverter.fromPluginManifests(pluginManifestList);
}
- private static List<PluginManifest> getPluginManifestList(Collection<PluginMetadata> metadata) {
+ private static List<PluginManifest> getPluginManifestList(Collection<PluginInfo> metadata) {
List<PluginManifest> 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<PluginMetadata, Object> installedExtensionsByPlugin = ArrayListMultimap.create();
+ ListMultimap<PluginInfo, Object> 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<PluginMetadata, Object> entry : installedExtensionsByPlugin.entries()) {
- PluginMetadata plugin = entry.getKey();
+ for (Map.Entry<PluginInfo, Object> 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<String, PluginMetadata> pluginByKeys = Maps.newHashMap();
- private final ServerUpgradeStatus serverUpgradeStatus;
- private static final Set<String> BLACKLISTED_PLUGINS = new HashSet<String>(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<String> 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<DefaultPluginMetadata> 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<PluginMetadata> getMetadata() {
- return pluginByKeys.values();
- }
-
- public PluginMetadata getMetadata(String pluginKey) {
- return pluginByKeys.get(pluginKey);
- }
-
- private PluginReferential getPluginReferential() {
- return PluginReferentialMetadataConverter.getInstalledPluginReferential(getMetadata());
- }
-
- private static Collection<File> listJarFiles(File pluginDir) {
- return listFiles(pluginDir, new String[] {FILE_EXTENSION_JAR}, false);
- }
-
- private enum FileToName implements Function<File, String> {
- 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:
+ * <ul>
+ * <li>installation of bundled plugins on first server startup</li>
+ * <li>installation of new plugins (effective after server startup)</li>
+ * <li>un-installation of plugins (effective after server startup)</li>
+ * <li>cancel pending installations/un-installations</li>
+ * <li>load plugin bytecode</li>
+ * </ul>
*/
public class ServerPluginRepository implements PluginRepository, Startable {
- private final ServerPluginJarsInstaller jarsInstaller;
- private final PluginClassloaders classloaders;
- private Map<String, Plugin> pluginsByKey;
+ private static final Logger LOG = Loggers.get(ServerPluginRepository.class);
+ private static final String FILE_EXTENSION_JAR = "jar";
+ private static final Set<String> 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<String> 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<String, PluginInfo> pluginInfosByKeys = new HashMap<>();
+ private final Map<String, Plugin> 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<String> keys) {
+ this.blacklistedPluginKeys = keys;
}
@Override
public void start() {
- jarsInstaller.install();
- Collection<PluginMetadata> 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<String> 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<PluginInfo> 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<String> 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<PluginInfo> 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<String, PluginInfo> getPluginInfosByKeys() {
+ return pluginInfosByKeys;
+ }
+
+ @Override
+ public Collection<PluginInfo> 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<PluginMetadata> 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<File, String> {
+ 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<File> 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<PluginMetadata> pluginMetadatas = retrieveAndSortPluginMetadata();
+ Collection<PluginInfo> infos = retrieveAndSortPluginMetadata();
JsonWriter jsonWriter = response.newJsonWriter();
jsonWriter.setSerializeEmptys(false);
jsonWriter.beginObject();
- writeMetadataList(jsonWriter, pluginMetadatas);
+ writeMetadataList(jsonWriter, infos);
jsonWriter.endObject();
jsonWriter.close();
}
- private SortedSet<PluginMetadata> retrieveAndSortPluginMetadata() {
+ private SortedSet<PluginInfo> 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<PluginMetadata> pluginMetadatas) {
+ private void writeMetadataList(JsonWriter jsonWriter, Collection<PluginInfo> 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<PluginMetadata> {
+ private enum NotCorePluginsPredicate implements Predicate<PluginInfo> {
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<DefaultPluginMetadata> plugins = pluginDownloader.getDownloadedPlugins();
- for (PluginMetadata pluginMetadata : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
+ Collection<PluginInfo> 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<DefaultPluginMetadata> plugins = serverPluginJarsInstaller.getUninstalledPlugins();
- for (PluginMetadata pluginMetadata : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
+ Collection<PluginInfo> 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<PluginMetadata> NAME_KEY_PLUGIN_METADATA_COMPARATOR = Ordering.natural()
+ public static final Ordering<PluginInfo> NAME_KEY_PLUGIN_METADATA_COMPARATOR = Ordering.natural()
.onResultOf(PluginMetadataToName.INSTANCE)
.compound(Ordering.natural().onResultOf(PluginMetadataToKey.INSTANCE));
public static final Comparator<Plugin> NAME_KEY_PLUGIN_ORDERING = Ordering.from(CASE_INSENSITIVE_ORDER)
@@ -70,23 +71,26 @@ public class PluginWSCommons {
public static final Comparator<PluginUpdate> 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<PluginMetadata, String> {
+ private enum PluginMetadataToName implements Function<PluginInfo, String> {
INSTANCE;
@Override
- public String apply(@Nonnull PluginMetadata input) {
+ public String apply(@Nonnull PluginInfo input) {
return input.getName();
}
}
- private enum PluginMetadataToKey implements Function<PluginMetadata, String> {
+ private enum PluginMetadataToKey implements Function<PluginInfo, String> {
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<PluginMetadata> {
- 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<String> 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<PluginMetadata> getPluginsMetadata() {
- return get(PluginRepository.class).getMetadata();
+ /**
+ * Used for WS api/updatecenter/installed_plugins, to be replaced by api/plugins/installed.
+ */
+ public Collection<PluginInfo> getPluginInfos() {
+ return get(PluginRepository.class).getPluginInfos();
}
public List<ViewProxy<Widget>> 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
@@ -38,20 +38,6 @@ public class DefaultServerFileSystemTest {
public TemporaryFolder temp = new TemporaryFolder();
@Test
- public void find_plugins() throws Exception {
- List<File> 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<File> 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(
new File(Resources.getResource(PATH + "shouldFindCheckstyleExtensions").toURI()), temp.newFolder(), null);
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.<PluginMetadata>emptyList());
+ when(pluginRepository.getPluginInfos()).thenReturn(Collections.<PluginInfo>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/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<String, Object> 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<PluginMetadata> getMetadata() {
- List<PluginMetadata> 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<DefaultPluginMetadata> 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/platform/SonarHomeTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/TestProjectUtils.java
index 66a4069fba1..00d579118ee 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/SonarHomeTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/TestProjectUtils.java
@@ -17,13 +17,24 @@
* 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;
+package org.sonar.server.plugins;
-import org.junit.Test;
+import org.apache.commons.io.FileUtils;
-public class SonarHomeTest {
- @Test
- public void iDontKnowHowToSimplyTestThisClass() {
+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<File> 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.<PluginMetadata>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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.codehaus.sonar.tests</groupId>
+ <artifactId>parent</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <modules>
+ <module>test-base-plugin</module>
+ <module>test-base-plugin-v2</module>
+ <module>test-core-plugin</module>
+ <module>test-extend-plugin</module>
+ <module>test-libs-plugin</module>
+ <module>test-require-plugin</module>
+ <module>test-requirenew-plugin</module>
+ </modules>
+
+</project>
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.codehaus.sonar.tests</groupId>
+ <artifactId>test-base-plugin</artifactId>
+ <version>0.2-SNAPSHOT</version>
+ <packaging>sonar-plugin</packaging>
+ <name>Base Plugin</name>
+ <description>Simple standalone plugin. Used by other fake plugins.</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>4.5.4</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-packaging-maven-plugin</artifactId>
+ <version>1.13</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginKey>testbase</pluginKey>
+ <pluginClass>BasePlugin</pluginClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
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
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-base-plugin-v2/target/test-base-plugin-0.2-SNAPSHOT.jar
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.codehaus.sonar.tests</groupId>
+ <artifactId>test-base-plugin</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <packaging>sonar-plugin</packaging>
+ <name>Base Plugin</name>
+ <description>Simple standalone plugin. Used by other fake plugins.</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>4.5.4</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-packaging-maven-plugin</artifactId>
+ <version>1.13</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginKey>testbase</pluginKey>
+ <pluginClass>BasePlugin</pluginClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
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
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-base-plugin/target/test-base-plugin-0.1-SNAPSHOT.jar
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.codehaus.sonar.tests</groupId>
+ <artifactId>test-core-plugin</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <packaging>sonar-plugin</packaging>
+ <name>Test Core Plugin</name>
+ <description>Fake core plugin used by tests</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>4.5.4</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-packaging-maven-plugin</artifactId>
+ <version>1.13</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginKey>core</pluginKey>
+ <pluginClass>CorePlugin</pluginClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
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
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-core-plugin/target/test-core-plugin-0.1-SNAPSHOT.jar
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.codehaus.sonar.tests</groupId>
+ <artifactId>test-extend-plugin</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <packaging>sonar-plugin</packaging>
+ <name>Test Extend Plugin</name>
+ <description>Fake plugin that extends the plugin with key "base"</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>4.5.4</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-packaging-maven-plugin</artifactId>
+ <version>1.13</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginKey>testextend</pluginKey>
+ <pluginClass>ExtendPlugin</pluginClass>
+ <basePlugin>testbase</basePlugin>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
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
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-extend-plugin/target/test-extend-plugin-0.1-SNAPSHOT.jar
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.codehaus.sonar.tests</groupId>
+ <artifactId>test-libs-plugin</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <packaging>sonar-plugin</packaging>
+ <name>Test Libs Plugin</name>
+ <description>Fake plugin that embeds some libraries</description>
+
+ <dependencies>
+ <!-- embedded libs. Chosen because small ! -->
+ <dependency>
+ <groupId>commons-email</groupId>
+ <artifactId>commons-email</artifactId>
+ <version>20030310.165926</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-daemon</groupId>
+ <artifactId>commons-daemon</artifactId>
+ <version>1.0.15</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>4.5.4</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-packaging-maven-plugin</artifactId>
+ <version>1.13</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginKey>testlibs</pluginKey>
+ <pluginClass>LibsPlugin</pluginClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
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
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-libs-plugin/target/test-libs-plugin-0.1-SNAPSHOT.jar
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.codehaus.sonar.tests</groupId>
+ <artifactId>test-require-plugin</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <packaging>sonar-plugin</packaging>
+ <name>Test Require Plugin</name>
+ <description>This fake plugin depends on test-base-plugin</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>4.5.4</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-packaging-maven-plugin</artifactId>
+ <version>1.13</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginKey>testrequire</pluginKey>
+ <pluginClass>RequirePlugin</pluginClass>
+ <requirePlugins>testbase:0.1</requirePlugins>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
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
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-require-plugin/target/test-require-plugin-0.1-SNAPSHOT.jar
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.codehaus.sonar.tests</groupId>
+ <artifactId>test-requirenew-plugin</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ <packaging>sonar-plugin</packaging>
+ <name>Test Require New Plugin</name>
+ <description>This fake plugin requires a version of test-base-plugin that is not installed</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-plugin-api</artifactId>
+ <version>4.5.4</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <sourceDirectory>src</sourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.sonar</groupId>
+ <artifactId>sonar-packaging-maven-plugin</artifactId>
+ <version>1.13</version>
+ <extensions>true</extensions>
+ <configuration>
+ <pluginKey>testrequire</pluginKey>
+ <pluginClass>RequirePlugin</pluginClass>
+ <requirePlugins>testbase:0.2</requirePlugins>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
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
--- /dev/null
+++ b/server/sonar-server/src/test/projects/test-requirenew-plugin/target/test-requirenew-plugin-0.1-SNAPSHOT.jar
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/extension.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/foo-plugin.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginClassLoadersTest/sonar-build-breaker-plugin-0.1.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginDownloaderTest/foo-plugin-1.0.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginExtensionMetadataTest/version1/extension.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginExtensionMetadataTest/version2/extension.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/foo-plugin-1.0.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/foo-plugin-2.0.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/not-a-plugin.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataLoaderTest/old-plugin.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginMetadataTest/foo-plugin.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/bar-plugin-1.0.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/foo-plugin-1.0.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/foo-plugin-2.0.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/not-a-plugin.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginJarsInstallerTest/require-sq-2.5.jar
+++ /dev/null
Binary files 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
--- a/server/sonar-server/src/test/resources/org/sonar/server/plugins/ServerPluginRepositoryTest/sonar-artifact-size-plugin-0.2.jar
+++ /dev/null
Binary files 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