aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pom.xml2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java25
-rw-r--r--sonar-core/src/main/java/org/sonar/core/plugins/PluginInstaller.java2
-rw-r--r--sonar-core/src/test/java/org/sonar/core/plugins/DefaultPluginMetadataTest.java2
-rw-r--r--sonar-core/src/test/java/org/sonar/core/plugins/PluginInstallerTest.java17
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginMetadata.java4
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/Platform.java3
-rw-r--r--sonar-server/src/main/java/org/sonar/server/plugins/InstalledPluginReferentialFactory.java93
-rw-r--r--sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java4
-rw-r--r--sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java64
-rw-r--r--sonar-server/src/main/java/org/sonar/server/plugins/PluginUpdate.java1
-rw-r--r--sonar-server/src/main/java/org/sonar/server/plugins/SonarUpdate.java1
-rw-r--r--sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java54
-rw-r--r--sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterMatrix.java167
-rw-r--r--sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java37
-rw-r--r--sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java23
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/updatecenter_controller.rb96
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_children.html.erb12
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_dependencies.html.erb22
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_status.html.erb4
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/available.html.erb20
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/index.html.erb53
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/system_updates.html.erb2
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/updates.html.erb45
-rw-r--r--sonar-server/src/test/java/org/sonar/server/plugins/PluginDeployerTest.java1
-rw-r--r--sonar-server/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java26
-rw-r--r--sonar-server/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixTest.java172
27 files changed, 414 insertions, 538 deletions
diff --git a/pom.xml b/pom.xml
index 54e58423ceb..746f1cd7ae1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -580,7 +580,7 @@
<dependency>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-update-center-common</artifactId>
- <version>1.4</version>
+ <version>1.5-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.codehaus.sonar</groupId>
diff --git a/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java b/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java
index f08e78de9a4..fa6a8a0f901 100644
--- a/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java
+++ b/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java
@@ -29,10 +29,12 @@ import org.sonar.updatecenter.common.Version;
import java.io.File;
import java.util.List;
+import static com.google.common.collect.Lists.newArrayList;
+
public class DefaultPluginMetadata implements PluginMetadata, Comparable<PluginMetadata> {
private File file;
- private List<File> deployedFiles = Lists.newArrayList();
- private List<File> deprecatedExtensions = Lists.newArrayList();
+ private List<File> deployedFiles = newArrayList();
+ private List<File> deprecatedExtensions = newArrayList();
private String[] pathsToInternalDeps = new String[0];
private String key;
private String version;
@@ -48,6 +50,8 @@ public class DefaultPluginMetadata implements PluginMetadata, Comparable<PluginM
private String basePlugin;
private boolean core;
private String implementationBuild;
+ private String parent;
+ private String[] requiredPlugins = new String[0];
private DefaultPluginMetadata() {
}
@@ -178,6 +182,23 @@ public class DefaultPluginMetadata implements PluginMetadata, Comparable<PluginM
return this;
}
+ public String getParent() {
+ return parent != null ? parent : key;
+ }
+
+ public DefaultPluginMetadata setParent(String parent) {
+ this.parent = parent;
+ return this;
+ }
+
+ public String[] getRequiredPlugins() {
+ return requiredPlugins;
+ }
+
+ public void setRequiredPlugins(String[] requiredPlugins) {
+ this.requiredPlugins = requiredPlugins;
+ }
+
/**
* Find out if this plugin is compatible with a given version of Sonar.
* The version of sonar must be greater than or equal to the minimal version
diff --git a/sonar-core/src/main/java/org/sonar/core/plugins/PluginInstaller.java b/sonar-core/src/main/java/org/sonar/core/plugins/PluginInstaller.java
index 117011a9a42..af469176a28 100644
--- a/sonar-core/src/main/java/org/sonar/core/plugins/PluginInstaller.java
+++ b/sonar-core/src/main/java/org/sonar/core/plugins/PluginInstaller.java
@@ -119,6 +119,8 @@ public class PluginInstaller {
metadata.setUseChildFirstClassLoader(manifest.isUseChildFirstClassLoader());
metadata.setBasePlugin(manifest.getBasePlugin());
metadata.setImplementationBuild(manifest.getImplementationBuild());
+ metadata.setParent(manifest.getParent());
+ metadata.setRequiredPlugins(manifest.getRequiresPlugins());
metadata.setCore(isCore);
return metadata;
diff --git a/sonar-core/src/test/java/org/sonar/core/plugins/DefaultPluginMetadataTest.java b/sonar-core/src/test/java/org/sonar/core/plugins/DefaultPluginMetadataTest.java
index 0714f5bdf23..83eeab7a47a 100644
--- a/sonar-core/src/test/java/org/sonar/core/plugins/DefaultPluginMetadataTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/plugins/DefaultPluginMetadataTest.java
@@ -35,6 +35,7 @@ public class DefaultPluginMetadataTest {
public void testGettersAndSetters() {
DefaultPluginMetadata metadata = DefaultPluginMetadata.create(new File("sonar-checkstyle-plugin.jar"));
metadata.setKey("checkstyle")
+ .setParent("java")
.setLicense("LGPL")
.setDescription("description")
.setHomepage("http://home")
@@ -48,6 +49,7 @@ public class DefaultPluginMetadataTest {
.setImplementationBuild("abcdef");
assertThat(metadata.getKey()).isEqualTo("checkstyle");
+ assertThat(metadata.getParent()).isEqualTo("java");
assertThat(metadata.getLicense()).isEqualTo("LGPL");
assertThat(metadata.getDescription()).isEqualTo("description");
assertThat(metadata.getHomepage()).isEqualTo("http://home");
diff --git a/sonar-core/src/test/java/org/sonar/core/plugins/PluginInstallerTest.java b/sonar-core/src/test/java/org/sonar/core/plugins/PluginInstallerTest.java
index fcf328d4f0a..91eafaf5fab 100644
--- a/sonar-core/src/test/java/org/sonar/core/plugins/PluginInstallerTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/plugins/PluginInstallerTest.java
@@ -100,7 +100,24 @@ public class PluginInstallerTest {
assertThat(new File(toDir, "checkstyle-extension.xml")).exists();
}
+ @Test
+ public void should_extract_parent_information() throws IOException {
+ DefaultPluginMetadata metadata = extractor.extractMetadata(getFile("fake1bis-plugin-1.0.jar"), true);
+
+ assertThat(metadata.getKey()).isEqualTo("fake1bis");
+ assertThat(metadata.getParent()).isEqualTo("fake1");
+ }
+
+ @Test
+ public void should_extract_requires_plugin_information() throws IOException {
+ DefaultPluginMetadata metadata = extractor.extractMetadata(getFile("fake2-plugin-1.1.jar"), true);
+
+ assertThat(metadata.getKey()).isEqualTo("fake2");
+ assertThat(metadata.getRequiredPlugins()).isEqualTo(new String[]{"fake1:1.1"});
+ }
+
static File getFile(String filename) {
return FileUtils.toFile(PluginInstallerTest.class.getResource("/org/sonar/core/plugins/" + filename));
}
+
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginMetadata.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginMetadata.java
index 71d70cf6dc5..a8958e9f557 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginMetadata.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/platform/PluginMetadata.java
@@ -52,5 +52,9 @@ public interface PluginMetadata {
String getBasePlugin();
+ String getParent();
+
+ String[] getRequiredPlugins();
+
boolean isCore();
}
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
index fee24b7f1eb..7305d3f7699 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
@@ -79,6 +79,7 @@ import org.sonar.server.notifications.NotificationService;
import org.sonar.server.notifications.reviews.ReviewsNotificationManager;
import org.sonar.server.plugins.ApplicationDeployer;
import org.sonar.server.plugins.DefaultServerPluginRepository;
+import org.sonar.server.plugins.InstalledPluginReferentialFactory;
import org.sonar.server.plugins.PluginDeployer;
import org.sonar.server.plugins.PluginDownloader;
import org.sonar.server.plugins.ServerExtensionInstaller;
@@ -181,7 +182,9 @@ public final class Platform {
rootContainer.addSingleton(daoClass);
}
rootContainer.addSingleton(PluginDeployer.class);
+ rootContainer.addSingleton(InstalledPluginReferentialFactory.class);
rootContainer.addSingleton(DefaultServerPluginRepository.class);
+
rootContainer.addSingleton(DefaultServerFileSystem.class);
rootContainer.addSingleton(ApplicationDeployer.class);
rootContainer.addSingleton(JRubyI18n.class);
diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/InstalledPluginReferentialFactory.java b/sonar-server/src/main/java/org/sonar/server/plugins/InstalledPluginReferentialFactory.java
new file mode 100644
index 00000000000..f1fab59fe22
--- /dev/null
+++ b/sonar-server/src/main/java/org/sonar/server/plugins/InstalledPluginReferentialFactory.java
@@ -0,0 +1,93 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.server.plugins;
+
+import org.sonar.api.ServerComponent;
+import org.sonar.api.platform.PluginMetadata;
+import org.sonar.api.platform.PluginRepository;
+import org.sonar.api.platform.Server;
+import org.sonar.updatecenter.common.PluginCenter;
+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.Date;
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+public class InstalledPluginReferentialFactory implements ServerComponent {
+
+ private final PluginDeployer pluginDeployer;
+ private PluginRepository pluginRepository;
+ private Version sonarVersion;
+
+ public InstalledPluginReferentialFactory(PluginRepository pluginRepository, Server server, PluginDeployer pluginDeployer) {
+ this.pluginRepository = pluginRepository;
+ this.pluginDeployer = pluginDeployer;
+ this.sonarVersion = Version.create(server.getVersion());
+ }
+
+ public PluginCenter getPluginCenter() {
+ PluginReferential installedPluginReferential = getInstalledPluginReferential();
+ return PluginCenter.createForInstalledPlugins(installedPluginReferential, sonarVersion)
+ .setDate(new Date());
+ }
+
+ public void uninstall(String pluginKey) {
+ for (String key : getPluginCenter().findRemovableReleases(pluginKey)) {
+ pluginDeployer.uninstall(key);
+ }
+ }
+
+ public PluginReferential getInstalledPluginReferential() {
+ List<PluginManifest> pluginManifestList = getPluginManifestList();
+ return PluginReferentialManifestConverter.fromPluginManifests(pluginManifestList, sonarVersion);
+ }
+
+ private List<PluginManifest> getPluginManifestList() {
+ List<PluginManifest> pluginManifestList = newArrayList();
+ for (PluginMetadata metadata : pluginRepository.getMetadata()) {
+ if (!metadata.isCore()) {
+ pluginManifestList.add(toPluginManifest(metadata));
+ }
+ }
+ return pluginManifestList;
+ }
+
+ private PluginManifest toPluginManifest(PluginMetadata metadata) {
+ PluginManifest pluginManifest = new PluginManifest();
+ pluginManifest.setKey(metadata.getKey());
+ pluginManifest.setName(metadata.getName());
+ pluginManifest.setVersion(metadata.getVersion());
+ pluginManifest.setDescription(metadata.getDescription());
+ pluginManifest.setMainClass(metadata.getMainClass());
+ pluginManifest.setOrganization(metadata.getOrganization());
+ pluginManifest.setOrganizationUrl(metadata.getOrganizationUrl());
+ pluginManifest.setLicense(metadata.getLicense());
+ pluginManifest.setHomepage(metadata.getHomepage());
+ pluginManifest.setBasePlugin(metadata.getBasePlugin());
+ pluginManifest.setParent(metadata.getParent());
+ pluginManifest.setRequiresPlugins(metadata.getRequiredPlugins());
+ return pluginManifest;
+ }
+
+}
diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java b/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java
index 6a00e387275..f56a787cd2b 100644
--- a/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java
+++ b/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java
@@ -20,7 +20,6 @@
package org.sonar.server.plugins;
import com.google.common.base.Joiner;
-
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -192,6 +191,9 @@ public class PluginDeployer implements ServerComponent {
}
private void deploy(DefaultPluginMetadata plugin) {
+
+ // TODO check version, parent, dependencies, ...
+
LOG.info("Deploy plugin {}", Joiner.on(" / ").skipNulls().join(plugin.getName(), plugin.getVersion(), plugin.getImplementationBuild()));
Preconditions.checkState(plugin.isCompatibleWith(server.getVersion()),
diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java b/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java
index 6711a8f42bc..7b8430d3c4e 100644
--- a/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java
+++ b/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java
@@ -19,31 +19,33 @@
*/
package org.sonar.server.plugins;
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.sonar.api.ServerComponent;
import org.sonar.api.utils.HttpDownloader;
-import org.sonar.api.utils.Logs;
import org.sonar.api.utils.SonarException;
import org.sonar.server.platform.DefaultServerFileSystem;
-import org.sonar.updatecenter.common.Plugin;
import org.sonar.updatecenter.common.Release;
import org.sonar.updatecenter.common.Version;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
public class PluginDownloader implements ServerComponent {
- private UpdateCenterClient center;
+ private static final Logger LOG = LoggerFactory.getLogger(PluginDownloader.class);
+ private UpdateCenterMatrixFactory updateCenterMatrixFactory;
private HttpDownloader downloader;
private File downloadDir;
- public PluginDownloader(UpdateCenterClient center, HttpDownloader downloader, DefaultServerFileSystem fileSystem) {
- this.center = center;
+ public PluginDownloader(UpdateCenterMatrixFactory updateCenterMatrixFactory, HttpDownloader downloader, DefaultServerFileSystem fileSystem) {
+ this.updateCenterMatrixFactory = updateCenterMatrixFactory;
this.downloader = downloader;
this.downloadDir = fileSystem.getDownloadedPluginsDir();
try {
@@ -57,8 +59,8 @@ public class PluginDownloader implements ServerComponent {
/**
* for unit tests
*/
- PluginDownloader(UpdateCenterClient center, HttpDownloader downloader, File downloadDir) {
- this.center = center;
+ PluginDownloader(UpdateCenterMatrixFactory updateCenterMatrixFactory, HttpDownloader downloader, File downloadDir) {
+ this.updateCenterMatrixFactory = updateCenterMatrixFactory;
this.downloader = downloader;
this.downloadDir = downloadDir;
}
@@ -80,7 +82,7 @@ public class PluginDownloader implements ServerComponent {
public List<String> getDownloads() {
List<String> names = new ArrayList<String>();
- List<File> files = (List<File>) FileUtils.listFiles(downloadDir, new String[] { "jar" }, false);
+ List<File> files = (List<File>) FileUtils.listFiles(downloadDir, new String[]{"jar"}, false);
for (File file : files) {
names.add(file.getName());
}
@@ -88,29 +90,21 @@ public class PluginDownloader implements ServerComponent {
}
public void download(String pluginKey, Version version) {
- Plugin plugin = center.getCenter().getPlugin(pluginKey);
- if (plugin == null) {
- String message = "This plugin does not exist: " + pluginKey;
- Logs.INFO.warn(message);
- throw new SonarException(message);
- }
+ for (Release release : updateCenterMatrixFactory.getPluginCenter(false).findInstallablePlugins(pluginKey, version)) {
+ try {
+ downloadRelease(release);
- Release release = plugin.getRelease(version);
- if (release == null || StringUtils.isBlank(release.getDownloadUrl())) {
- String message = "This release can not be installed: " + pluginKey + ", version " + version;
- Logs.INFO.warn(message);
- throw new SonarException(message);
+ } catch (Exception e) {
+ String message = "Fail to download the plugin (" + release.getArtifact().getKey() + ", version " + version + ") from " + release.getDownloadUrl();
+ LOG.warn(message, e);
+ throw new SonarException(message, e);
+ }
}
+ }
- try {
- URI uri = new URI(release.getDownloadUrl());
- String filename = StringUtils.substringAfterLast(uri.getPath(), "/");
- downloader.download(uri, new File(downloadDir, filename));
-
- } catch (Exception e) {
- String message = "Fail to download the plugin (" + pluginKey + ", version " + version + ") from " + release.getDownloadUrl();
- Logs.INFO.warn(message, e);
- throw new SonarException(message, e);
- }
+ private void downloadRelease(Release release) throws URISyntaxException {
+ URI uri = new URI(release.getDownloadUrl());
+ String filename = StringUtils.substringAfterLast(uri.getPath(), "/");
+ downloader.download(uri, new File(downloadDir, filename));
}
}
diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/PluginUpdate.java b/sonar-server/src/main/java/org/sonar/server/plugins/PluginUpdate.java
index 71ad6c7500d..ec3ed36077d 100644
--- a/sonar-server/src/main/java/org/sonar/server/plugins/PluginUpdate.java
+++ b/sonar-server/src/main/java/org/sonar/server/plugins/PluginUpdate.java
@@ -23,6 +23,7 @@ import org.sonar.updatecenter.common.Plugin;
import org.sonar.updatecenter.common.Release;
import org.sonar.updatecenter.common.Version;
+@Deprecated
public final class PluginUpdate {
public enum Status {
diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/SonarUpdate.java b/sonar-server/src/main/java/org/sonar/server/plugins/SonarUpdate.java
index ec2c02d767f..6b4ef69f904 100644
--- a/sonar-server/src/main/java/org/sonar/server/plugins/SonarUpdate.java
+++ b/sonar-server/src/main/java/org/sonar/server/plugins/SonarUpdate.java
@@ -25,6 +25,7 @@ import org.sonar.updatecenter.common.Release;
import java.util.ArrayList;
import java.util.List;
+@Deprecated
public final class SonarUpdate implements Comparable<SonarUpdate> {
private Release release;
diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java b/sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java
index ee1673f9e1b..84b44fa7bb8 100644
--- a/sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java
+++ b/sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterClient.java
@@ -28,8 +28,8 @@ import org.sonar.api.PropertyType;
import org.sonar.api.ServerComponent;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.UriReader;
-import org.sonar.updatecenter.common.UpdateCenter;
-import org.sonar.updatecenter.common.UpdateCenterDeserializer;
+import org.sonar.updatecenter.common.PluginReferential;
+import org.sonar.updatecenter.common.PluginReferentialDeserializer;
import java.io.InputStream;
import java.net.URI;
@@ -43,29 +43,28 @@ import java.util.Date;
* @since 2.4
*/
@Properties({
- @Property(
- key = "sonar.updatecenter.activate",
- defaultValue = "true",
- name = "Enable Update Center",
- project = false,
- global = false, // hidden from UI
- category = "Update Center",
- type = PropertyType.BOOLEAN),
- @Property(
- key = UpdateCenterClient.URL_PROPERTY,
- defaultValue = "http://update.sonarsource.org/update-center.properties",
- name = "Update Center URL",
- project = false,
- global = false, // hidden from UI
- category = "Update Center")
+ @Property(
+ key = "sonar.updatecenter.activate",
+ defaultValue = "true",
+ name = "Enable Update Center",
+ project = false,
+ global = false, // hidden from UI
+ category = "Update Center",
+ type = PropertyType.BOOLEAN),
+ @Property(
+ key = UpdateCenterClient.URL_PROPERTY,
+ defaultValue = "http://update.sonarsource.org/update-center.properties",
+ name = "Update Center URL",
+ project = false,
+ global = false, // hidden from UI
+ category = "Update Center")
})
public class UpdateCenterClient implements ServerComponent {
public static final String URL_PROPERTY = "sonar.updatecenter.url";
public static final int PERIOD_IN_MILLISECONDS = 60 * 60 * 1000;
-
private URI uri;
- private UpdateCenter center = null;
+ private PluginReferential pluginReferential = null;
private long lastRefreshDate = 0;
private UriReader uriReader;
@@ -75,16 +74,16 @@ public class UpdateCenterClient implements ServerComponent {
LoggerFactory.getLogger(getClass()).info("Update center: " + uriReader.description(uri));
}
- public UpdateCenter getCenter() {
- return getCenter(false);
+ public PluginReferential getPluginReferential() {
+ return getPlugins(false);
}
- public UpdateCenter getCenter(boolean forceRefresh) {
- if (center == null || forceRefresh || needsRefresh()) {
- center = init();
+ public PluginReferential getPlugins(boolean forceRefresh) {
+ if (pluginReferential == null || forceRefresh || needsRefresh()) {
+ pluginReferential = init();
lastRefreshDate = System.currentTimeMillis();
}
- return center;
+ return pluginReferential;
}
public Date getLastRefreshDate() {
@@ -95,15 +94,14 @@ public class UpdateCenterClient implements ServerComponent {
return lastRefreshDate + PERIOD_IN_MILLISECONDS < System.currentTimeMillis();
}
- private UpdateCenter init() {
+ private PluginReferential init() {
InputStream input = null;
try {
String content = uriReader.readString(uri, Charsets.UTF_8);
java.util.Properties properties = new java.util.Properties();
input = IOUtils.toInputStream(content, Charsets.UTF_8.name());
properties.load(input);
- return UpdateCenterDeserializer.fromProperties(properties);
-
+ return PluginReferentialDeserializer.fromProperties(properties);
} catch (Exception e) {
LoggerFactory.getLogger(getClass()).error("Fail to connect to update center", e);
diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterMatrix.java b/sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterMatrix.java
deleted file mode 100644
index b7caf70ca76..00000000000
--- a/sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterMatrix.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.server.plugins;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import org.sonar.updatecenter.common.*;
-
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedSet;
-
-public final class UpdateCenterMatrix {
-
- private UpdateCenter center;
- private Version installedSonarVersion;
- private Map<Plugin, Version> installedPlugins = Maps.newHashMap();
- private List<String> pendingPluginFilenames = Lists.newArrayList();
- private Date date;
-
- public UpdateCenterMatrix(UpdateCenter center, Version installedSonarVersion) {
- this.center = center;
- this.installedSonarVersion = installedSonarVersion;
- }
-
- public UpdateCenterMatrix registerInstalledPlugin(String pluginKey, Version pluginVersion) {
- Plugin plugin = center.getPlugin(pluginKey);
- if (plugin != null) {
- installedPlugins.put(plugin, pluginVersion);
- }
- return this;
- }
-
- /**
- * Used by ruby webapp
- */
- public UpdateCenter getCenter() {
- return center;
- }
-
- public UpdateCenterMatrix registerPendingPluginsByFilename(String filename) {
- pendingPluginFilenames.add(filename);
- return this;
- }
-
- public List<PluginUpdate> findAvailablePlugins() {
- Version adjustedSonarVersion = getAdjustedSonarVersion();
-
- List<PluginUpdate> availables = Lists.newArrayList();
- for (Plugin plugin : center.getPlugins()) {
- if (!installedPlugins.containsKey(plugin) && !isAlreadyDownloaded(plugin)) {
- Release release = plugin.getLastCompatibleRelease(adjustedSonarVersion);
- if (release != null) {
- availables.add(PluginUpdate.createWithStatus(release, PluginUpdate.Status.COMPATIBLE));
-
- } else {
- release = plugin.getLastCompatibleReleaseIfUpgrade(adjustedSonarVersion);
- if (release != null) {
- availables.add(PluginUpdate.createWithStatus(release, PluginUpdate.Status.REQUIRE_SONAR_UPGRADE));
- }
- }
- }
- }
- return availables;
- }
-
- private boolean isAlreadyDownloaded(Artifact artifact) {
- for (Release r : artifact.getReleases()) {
- if (pendingPluginFilenames.contains(r.getFilename())) {
- // already downloaded
- return true;
- }
- }
- return false;
- }
-
- public List<PluginUpdate> findPluginUpdates() {
- Version adjustedSonarVersion = getAdjustedSonarVersion();
-
- List<PluginUpdate> updates = Lists.newArrayList();
- for (Map.Entry<Plugin, Version> entry : installedPlugins.entrySet()) {
- Plugin plugin = entry.getKey();
- if (!isAlreadyDownloaded(plugin)) {
- Version pluginVersion = entry.getValue();
- for (Release release : plugin.getReleasesGreaterThan(pluginVersion)) {
- updates.add(PluginUpdate.createForPluginRelease(release, adjustedSonarVersion));
- }
- }
- }
- return updates;
- }
-
- public List<SonarUpdate> findSonarUpdates() {
- List<SonarUpdate> updates = Lists.newArrayList();
- SortedSet<Release> releases = center.getSonar().getReleasesGreaterThan(installedSonarVersion);
- for (Release release : releases) {
- updates.add(createSonarUpdate(release));
- }
- return updates;
- }
-
- SonarUpdate createSonarUpdate(Release sonarRelease) {
- SonarUpdate update = new SonarUpdate(sonarRelease);
- for (Map.Entry<Plugin, Version> entry : installedPlugins.entrySet()) {
- Plugin plugin = entry.getKey();
- Version pluginVersion = entry.getValue();
- Release pluginRelease = plugin.getRelease(pluginVersion);
-
- if (pluginRelease != null && pluginRelease.supportSonarVersion(sonarRelease.getVersion())) {
- update.addCompatiblePlugin(plugin);
-
- } else {
- // search for a compatible plugin upgrade
- boolean ok = false;
- Release compatibleRelease = null;
- for (Release greaterPluginRelease : plugin.getReleasesGreaterThan(pluginVersion)) {
- if (greaterPluginRelease.supportSonarVersion(sonarRelease.getVersion())) {
- compatibleRelease = greaterPluginRelease;
- ok = true;
- }
- }
- if (ok) {
- update.addPluginToUpgrade(compatibleRelease);
- } else {
- update.addIncompatiblePlugin(plugin);
- }
- }
- }
- return update;
- }
-
- public Date getDate() {
- return date;
- }
-
- public UpdateCenterMatrix setDate(Date d) {
- this.date = d;
- return this;
- }
-
- /**
- * Update center declares RELEASE versions of Sonar, for instance 3.2 but not 3.2-SNAPSHOT.
- * We assume that SNAPSHOT, milestones and release candidates of Sonar support the
- * same plugins than related RELEASE.
- */
- private Version getAdjustedSonarVersion() {
- return Version.createRelease(installedSonarVersion.toString());
- }
-}
diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java b/sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java
index fec82bd17d7..da8b9fe5c38 100644
--- a/sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java
+++ b/sonar-server/src/main/java/org/sonar/server/plugins/UpdateCenterMatrixFactory.java
@@ -20,10 +20,9 @@
package org.sonar.server.plugins;
import org.sonar.api.ServerComponent;
-import org.sonar.api.platform.PluginMetadata;
-import org.sonar.api.platform.PluginRepository;
import org.sonar.api.platform.Server;
-import org.sonar.updatecenter.common.UpdateCenter;
+import org.sonar.updatecenter.common.PluginCenter;
+import org.sonar.updatecenter.common.PluginReferential;
import org.sonar.updatecenter.common.Version;
/**
@@ -33,31 +32,25 @@ public final class UpdateCenterMatrixFactory implements ServerComponent {
private UpdateCenterClient centerClient;
private Version sonarVersion;
- private PluginDownloader downloader;
- private PluginRepository pluginRepository;
+ private InstalledPluginReferentialFactory installedPluginReferentialFactory;
- public UpdateCenterMatrixFactory(UpdateCenterClient centerClient, PluginRepository pluginRepository, Server server, PluginDownloader downloader) {
+ public UpdateCenterMatrixFactory(UpdateCenterClient centerClient, InstalledPluginReferentialFactory installedPluginReferentialFactory, Server server) {
this.centerClient = centerClient;
- this.pluginRepository = pluginRepository;
+ this.installedPluginReferentialFactory = installedPluginReferentialFactory;
this.sonarVersion = Version.create(server.getVersion());
- this.downloader = downloader;
}
- public UpdateCenterMatrix getMatrix(boolean refresh) {
- UpdateCenter center = centerClient.getCenter(refresh);
- UpdateCenterMatrix matrix = null;
- if (center != null) {
- matrix = new UpdateCenterMatrix(center, sonarVersion);
- matrix.setDate(centerClient.getLastRefreshDate());
-
- for (PluginMetadata metadata : pluginRepository.getMetadata()) {
- matrix.registerInstalledPlugin(metadata.getKey(), Version.create(metadata.getVersion()));
- }
- for (String filename : downloader.getDownloads()) {
- matrix.registerPendingPluginsByFilename(filename);
- }
+ public PluginCenter getPluginCenter(boolean refreshUpdateCenter) {
+ PluginReferential updateCenterPluginReferential = centerClient.getPlugins(refreshUpdateCenter);
+ if (updateCenterPluginReferential != null) {
+ return PluginCenter.create(updateCenterPluginReferential,
+ installedPluginReferentialFactory.getInstalledPluginReferential(),
+ sonarVersion)
+ .setDate(centerClient.getLastRefreshDate());
+ } else {
+ return null;
}
- return matrix;
}
+
}
diff --git a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
index e1a0ba1a55f..1b8d27f3b4e 100644
--- a/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
+++ b/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
@@ -72,12 +72,13 @@ import org.sonar.server.platform.ServerIdGenerator;
import org.sonar.server.platform.ServerSettings;
import org.sonar.server.platform.SettingsChangeNotifier;
import org.sonar.server.plugins.DefaultServerPluginRepository;
+import org.sonar.server.plugins.InstalledPluginReferentialFactory;
import org.sonar.server.plugins.PluginDeployer;
import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.UpdateCenterMatrix;
import org.sonar.server.plugins.UpdateCenterMatrixFactory;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
+import org.sonar.updatecenter.common.PluginCenter;
import org.sonar.updatecenter.common.Version;
import javax.annotation.Nullable;
@@ -177,7 +178,7 @@ public final class JRubyFacade {
}
public void uninstallPlugin(String pluginKey) {
- get(PluginDeployer.class).uninstall(pluginKey);
+ get(InstalledPluginReferentialFactory.class).uninstall(pluginKey);
}
public void cancelPluginUninstalls() {
@@ -188,8 +189,12 @@ public final class JRubyFacade {
return get(PluginDeployer.class).getUninstalls();
}
- public UpdateCenterMatrix getUpdateCenterMatrix(boolean forceReload) {
- return get(UpdateCenterMatrixFactory.class).getMatrix(forceReload);
+ public PluginCenter getUpdatePluginCenter(boolean forceReload) {
+ return get(UpdateCenterMatrixFactory.class).getPluginCenter(forceReload);
+ }
+
+ public PluginCenter getInstalledPluginCenter() {
+ return get(InstalledPluginReferentialFactory.class).getPluginCenter();
}
// PLUGINS ------------------------------------------------------------------
@@ -325,7 +330,7 @@ public final class JRubyFacade {
public void ruleSeverityChanged(int parentProfileId, int activeRuleId, int oldSeverityId, int newSeverityId, String userName) {
getProfilesManager().ruleSeverityChanged(parentProfileId, activeRuleId, RulePriority.values()[oldSeverityId],
- RulePriority.values()[newSeverityId], userName);
+ RulePriority.values()[newSeverityId], userName);
}
public void ruleDeactivated(int parentProfileId, int deactivatedRuleId, String userName) {
@@ -521,10 +526,10 @@ public final class JRubyFacade {
// notifier is null when creating the administrator in the migration script 011.
if (notifier != null) {
notifier.onNewUser(NewUserHandler.Context.builder()
- .setLogin(fields.get("login"))
- .setName(fields.get("name"))
- .setEmail(fields.get("email"))
- .build());
+ .setLogin(fields.get("login"))
+ .setName(fields.get("name"))
+ .setEmail(fields.get("email"))
+ .build());
}
}
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/updatecenter_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/updatecenter_controller.rb
index 2449acb4a9d..81bda497d97 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/updatecenter_controller.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/updatecenter_controller.rb
@@ -29,53 +29,55 @@ class UpdatecenterController < ApplicationController
@uninstalls=java_facade.getPluginUninstalls()
@downloads=java_facade.getPluginDownloads()
- @user_plugins=user_plugins()
- @core_plugins=core_plugins()
+ load_plugin_center
+ @plugins = installed_plugins
end
- def updates
+ def available
@uninstalls=java_facade.getPluginUninstalls()
@downloads=java_facade.getPluginDownloads()
+ @update_center_referential=nil
+ @updates_by_category={}
- @center=nil
- @matrix=nil
- @updates_by_plugin={}
- @user_plugins={}
- @last_compatible={}
-
- user_plugins.each do |plugin|
- @user_plugins[plugin.getKey()]=plugin.getVersion()
- end
-
- load_matrix()
- if @matrix
- @center=@matrix.getCenter()
-
- @matrix.findPluginUpdates().each do |update|
- plugin=update.getPlugin()
- @updates_by_plugin[plugin]||=[]
- @updates_by_plugin[plugin]<<update
- if update.isCompatible
- @last_compatible[plugin.getKey()]=update.getRelease().getVersion()
+ load_plugin_center()
+ if @update_plugin_center
+ @update_plugin_center.findAvailablePlugins().each do |update|
+ already_download = update.plugin.releases.find {|release| @downloads.include? release.filename }
+ if !already_download
+ category = update.plugin.category||''
+ @updates_by_category[category]||=[]
+ @updates_by_category[category]<<update
end
end
end
end
- def available
+ def updates
@uninstalls=java_facade.getPluginUninstalls()
@downloads=java_facade.getPluginDownloads()
- @center=nil
- @updates_by_category={}
+ @update_center_referential=nil
+ @update_plugin_center=nil
+ @updates_by_plugin={}
+ @installed_plugins={}
+ @last_compatible={}
+
+ load_plugin_center()
+ if @update_plugin_center
+ installed_plugins.each do |plugin|
+ @installed_plugins[plugin.getKey()]=plugin.lastRelease.getVersion()
+ end
- load_matrix()
- if @matrix
- @center=@matrix.getCenter()
- @matrix.findAvailablePlugins().each do |update|
- category=update.getPlugin().getCategory()||''
- @updates_by_category[category]||=[]
- @updates_by_category[category]<<update
+ @update_plugin_center.findPluginUpdates().each do |update|
+ plugin = update.plugin
+ already_download = update.plugin.releases.find {|release| @downloads.include? release.filename }
+ if !already_download
+ @updates_by_plugin[plugin]||=[]
+ @updates_by_plugin[plugin]<<update
+ if update.isCompatible
+ @last_compatible[plugin.key]=update.release.version
+ end
+ end
end
end
end
@@ -121,19 +123,23 @@ class UpdatecenterController < ApplicationController
@uninstalls=java_facade.getPluginUninstalls()
@downloads=java_facade.getPluginDownloads()
- @center=nil
- @matrix=nil
+ @update_center_referential=nil
+ @update_plugin_center=nil
@sonar_updates=[]
- load_matrix()
- if @matrix
- @center=@matrix.getCenter()
- @sonar_updates=@matrix.findSonarUpdates()
+ load_plugin_center()
+ if @update_plugin_center
+ @sonar_updates=@update_plugin_center.findSonarUpdates()
end
end
private
- def load_matrix
- @matrix=java_facade.getUpdateCenterMatrix(params[:reload]=='true')
+
+ def load_plugin_center
+ @update_plugin_center = java_facade.getUpdatePluginCenter(params[:reload]=='true')
+ @update_center_referential = @update_plugin_center.updateCenterPluginReferential
+
+ @installed_plugin_center = java_facade.getInstalledPluginCenter()
+ @installed_plugin_referential = @installed_plugin_center.installedPluginReferential
end
def updatecenter_activated
@@ -143,11 +149,7 @@ class UpdatecenterController < ApplicationController
end
end
- def user_plugins
- java_facade.getPluginsMetadata().select{|plugin| !plugin.isCore()}.sort
- end
-
- def core_plugins
- java_facade.getPluginsMetadata().select{|plugin| plugin.isCore()}.sort
+ def installed_plugins
+ @installed_plugin_referential.plugins
end
end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_children.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_children.html.erb
new file mode 100644
index 00000000000..6b8cadcba13
--- /dev/null
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_children.html.erb
@@ -0,0 +1,12 @@
+<% index = 0 %>
+<% children.each do |child| %>
+ <tr>
+ <% if index == 0 %>
+ <td class="thin nowrap"><b>Includes:</b></td>
+ <% else %>
+ <td>&nbsp;</td>
+ <% end %>
+ <td><span><%= child.name -%></span> : <span><%= child.description -%></span></td>
+ </tr>
+ <% index = index + 1 %>
+<% end %> \ No newline at end of file
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_dependencies.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_dependencies.html.erb
new file mode 100644
index 00000000000..111fa5bb4ed
--- /dev/null
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_dependencies.html.erb
@@ -0,0 +1,22 @@
+<% if release %>
+ <% release.outgoingDependencies.each_with_index do |outgoing_release, index| %>
+ <tr>
+ <% if index == 0 %>
+ <td class="thin nowrap"><b>Require plugins:</b></td>
+ <% else %>
+ <td>&nbsp;</td>
+ <% end %>
+ <td><span><%= outgoing_release.artifact.name -%> version <%= outgoing_release.version.name -%></span></td>
+ </tr>
+ <% end %>
+ <% release.incomingDependencies.each_with_index do |incoming_release, index| %>
+ <tr>
+ <% if index == 0 %>
+ <td class="thin nowrap"><b>Incoming plugins:</b></td>
+ <% else %>
+ <td>&nbsp;</td>
+ <% end %>
+ <td><span><%= incoming_release.artifact.name -%> version <%= incoming_release.version.name -%></span></td>
+ </tr>
+ <% end %>
+<% end %> \ No newline at end of file
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_status.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_status.html.erb
index 00f473ee3a1..5b978f4f9df 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_status.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/_status.html.erb
@@ -1,7 +1,7 @@
-<% if @center.nil? %>
+<% if @update_plugin_center.nil? %>
<p class="error">Not connected to update center. Please check your internet connection and logs.</p>
<% else %>
<p class="notes">
- Updated on <%= @matrix.getDate() -%>. <%= link_to 'Refresh', :action => action, :reload => true %>
+ Updated on <%= @update_center_referential.getDate() -%>. <%= link_to 'Refresh', :action => action, :reload => true %>
</p>
<% end %> \ No newline at end of file
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/available.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/available.html.erb
index 0f5defd15af..3eb144d865f 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/available.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/available.html.erb
@@ -20,7 +20,7 @@ function installPlugin(key) {
<%= render :partial => 'updatecenter/operations' -%>
-<% if @center %>
+<% if @update_plugin_center %>
<% @updates_by_category.keys.sort_by{|c| c.downcase }.each do |category|
updates=@updates_by_category[category]
%>
@@ -31,8 +31,9 @@ function installPlugin(key) {
</tr>
</thead>
<tbody>
- <% updates.sort_by{|c| c.getPlugin().getName()}.each do |update|
- plugin=update.getPlugin()
+ <% updates.sort_by{|update| update.plugin.key}.each do |update|
+ children = update.plugin.children
+ plugin = update.plugin
%>
<tr class="<%= cycle('even','odd', :name => category) -%>">
<td width="150" nowrap>
@@ -42,6 +43,19 @@ function installPlugin(key) {
<%= plugin.getDescription() %>
<div id="detail-<%= plugin.getKey() -%>" style="display:none">
<table class="spaced width100">
+ <%= render :partial => 'updatecenter/children', :locals => {:children => children} %>
+ <% release = @update_plugin_center.findLatestCompatibleRelease(plugin.key) %>
+ <% release.outgoingDependencies.each_with_index do |outgoing_release, index| %>
+ <tr>
+ <% if index == 0 %>
+ <td class="thin nowrap"><b>Installing this plugin will also install:</b></td>
+ <% else %>
+ <td>&nbsp;</td>
+ <% end %>
+ <td><span><%= outgoing_release.artifact.name -%> version <%= outgoing_release.version.name -%></span></td>
+ </tr>
+ <% end %>
+
<% if plugin.getLicense() %>
<tr>
<td class="thin nowrap"><b>License:</b> </td><td><%= h(plugin.getLicense()) %></td>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/index.html.erb
index f483d55f8e3..5921c38589f 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/index.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/index.html.erb
@@ -16,19 +16,42 @@
</tr>
</thead>
<tbody>
- <% if @user_plugins.empty? %>
+ <% if @plugins.empty? %>
<tr class="even"><td colspan="5">No plugins</td></tr>
<% else
- @user_plugins.each do |plugin|
+ @plugins.each do |plugin|
%>
<tr class="select <%= cycle('even', 'odd', :name => 'user') -%>" id="select_<%= plugin.getKey() -%>">
<td width="1%" nowrap><b><a href="#plugin" onclick="showPlugin('<%= plugin.getKey() -%>')"><%= h(plugin.getName()) -%></a></b> <span class="note">[<%= h plugin.getKey() -%>]</span></td>
- <td><%= plugin.getVersion() || '-' -%></td>
+ <td><%= plugin.lastRelease.getVersion() || '-' -%></td>
<td>
<%= plugin.getDescription() -%>
-
<div id="detail-<%= plugin.getKey() -%>" style="display:none">
+
<table class="spaced width100">
+ <%= render :partial => 'updatecenter/children', :locals => {:children => plugin.children} %>
+ <% release = @installed_plugin_referential.findLatestRelease(plugin.key) %>
+ <% release.outgoingDependencies.each_with_index do |outgoing_release, index| %>
+ <tr>
+ <% if index == 0 %>
+ <td class="thin nowrap"><b>Depends upon:</b></td>
+ <% else %>
+ <td>&nbsp;</td>
+ <% end %>
+ <td><span><%= outgoing_release.artifact.name -%> version <%= outgoing_release.version.name -%></span></td>
+ </tr>
+ <% end %>
+ <% release.incomingDependencies.each_with_index do |incoming_release, index| %>
+ <tr>
+ <% if index == 0 %>
+ <td class="thin nowrap"><b>Uninstalling this plugin will also uninstall:</b></td>
+ <% else %>
+ <td>&nbsp;</td>
+ <% end %>
+ <td><span><%= incoming_release.artifact.name -%> version <%= incoming_release.version.name -%></span></td>
+ </tr>
+ <% end %>
+
<% if plugin.getLicense() %><tr><td class="thin nowrap"><b>License:</b> </td><td><%= plugin.getLicense() -%></td></tr><% end %>
<% if plugin.getOrganization() %>
<tr><td class="thin nowrap"><b>Author:</b> </td>
@@ -36,10 +59,10 @@
</tr>
<% end %>
- <% if plugin.getHomepage() %>
+ <% if plugin.getHomepageUrl() %>
<tr>
<td colspan="2">
- <%= link_to 'Homepage', plugin.getHomepage(), :class => 'external' -%>
+ <%= link_to 'Homepage', plugin.getHomepageUrl(), :class => 'external' -%>
</td>
</tr>
<% end %>
@@ -59,23 +82,5 @@
</tbody>
</table>
- <div class="break30"> </div>
-
- <table class="data width100" id="system-plugins">
- <thead>
- <tr><th colspan="3"><h2>System plugins</h2></th></tr>
- </thead>
- <tbody>
- <%
- @core_plugins.each do |plugin|
- %>
- <tr class="<%= cycle('even','odd', :name => 'core') -%>" id="<%= u plugin.getKey() -%>">
- <td width="1%" nowrap><b><%= plugin.getName() -%></b> <span class="note">[<%= h plugin.getKey() -%>]</span></td>
- <td><%= plugin.getDescription() -%></td>
- </tr>
- <% end %>
- </tbody>
- </table>
-
</div>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/system_updates.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/system_updates.html.erb
index 11f0b26e862..e77bf8d7b11 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/system_updates.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/system_updates.html.erb
@@ -18,7 +18,7 @@
<%= render :partial => 'updatecenter/operations' -%>
- <% if @center %>
+ <% if @update_plugin_center %>
<% if @sonar_updates.empty? %>
<table class="data width100 marginbottom10">
<thead>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/updates.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/updates.html.erb
index d313e675353..eb679eb7da7 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/updates.html.erb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/views/updatecenter/updates.html.erb
@@ -14,7 +14,7 @@ function upgradePlugin(key) {
<%= render :partial => 'updatecenter/operations' -%>
- <% if @center %>
+ <% if @update_plugin_center %>
<table class="data width100 marginbottom10" id="plugin-updates">
<thead>
<tr><th colspan="2"><h2>Plugins</h2></th></tr>
@@ -32,23 +32,42 @@ function upgradePlugin(key) {
release=update.getRelease()
%>
<tr class="<%= css -%>">
- <td width="1%" nowrap><% if index==0 %><b><%= h(plugin.getName()) -%></b> <%= @user_plugins[plugin.getKey()] -%> -> <% end %></td>
- <td width="1%" nowrap><b><%= release.getVersion() -%></b></td>
- <td width="1%" nowrap><%= release_date(release.getDate()) if release.getDate() -%></td>
- <td><%= release.getDescription() -%></td>
- <td><%= link_to 'Release Notes', release.getChangelogUrl(), :class => 'external' if release.getChangelogUrl() %></td>
- <td>
- <% if update.isIncompatible() %>
- <%= image_tag 'warning.png' -%> Incompatible
- <% elsif update.requiresSonarUpgrade %>
- <%= image_tag 'warning.png' -%> Incompatible, requires to upgrade system
- <% end %>
- </td>
+ <td width="1%" nowrap><% if index==0 %><b><%= h(plugin.getName()) -%></b> <%= @installed_plugins[plugin.getKey()] -%> -> <% end %></td>
+ <td width="1%" nowrap><b><%= release.getVersion() -%></b></td>
+ <td width="1%" nowrap><%= release_date(release.getDate()) if release.getDate() -%></td>
+ <td><%= release.getDescription() -%></td>
+ <td><%= link_to 'Release Notes', release.getChangelogUrl(), :class => 'external' if release.getChangelogUrl() %></td>
+ <td>
+ <% if update.isIncompatible() %>
+ <%= image_tag 'warning.png' -%> Incompatible
+ <% elsif update.requiresSonarUpgrade %>
+ <%= image_tag 'warning.png' -%> Incompatible, requires to upgrade system
+ <% end %>
+ </td>
</tr>
<%
end
%>
<% if @last_compatible[plugin.getKey()] %>
+
+ <% release = @update_plugin_center.findLatestCompatibleRelease(plugin.key)
+ releases = release.outgoingDependencies + release.incomingDependencies
+ %>
+ <% releases.each_with_index do |outgoing_release, index| %>
+ <tr class="<%= css -%>">
+ <td> </td>
+ <td> </td>
+ <% if index == 0 %>
+ <td class="thin nowrap"><b>Updating this plugin will also update:</b></td>
+ <% else %>
+ <td >&nbsp;</td>
+ <% end %>
+ <td colspan="4">
+ <span><%= outgoing_release.artifact.name -%> version <%= outgoing_release.version.name -%></span>
+ </td>
+ </tr>
+ <% end %>
+
<tr class="<%= css -%>">
<td> </td>
<td colspan="5">
diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/PluginDeployerTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/PluginDeployerTest.java
index 0078d749ffc..6eb396a4e71 100644
--- a/sonar-server/src/test/java/org/sonar/server/plugins/PluginDeployerTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/plugins/PluginDeployerTest.java
@@ -45,6 +45,7 @@ public class PluginDeployerTest {
private File deployDir;
private PluginDeployer deployer;
private Server server = mock(Server.class);
+ private UpdateCenterMatrixFactory updateCenterMatrixFactory;
@Rule
public TestName name = new TestName();
diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java
index dec99a70f4b..39eac2dac06 100644
--- a/sonar-server/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/plugins/UpdateCenterClientTest.java
@@ -25,20 +25,25 @@ import org.junit.Test;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.SonarException;
import org.sonar.api.utils.UriReader;
-import org.sonar.updatecenter.common.UpdateCenter;
+import org.sonar.updatecenter.common.PluginReferential;
import org.sonar.updatecenter.common.Version;
import java.net.URI;
import java.net.URISyntaxException;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
public class UpdateCenterClientTest {
+ private static final String BASE_URL = "http://update.sonarsource.org";
private UpdateCenterClient client;
private UriReader reader;
- private static final String BASE_URL = "http://update.sonarsource.org";
@Before
public void startServer() throws Exception {
@@ -50,9 +55,9 @@ public class UpdateCenterClientTest {
@Test
public void downloadUpdateCenter() throws URISyntaxException {
when(reader.readString(new URI(BASE_URL), Charsets.UTF_8)).thenReturn("sonar.versions=2.2,2.3");
- UpdateCenter center = client.getCenter();
+ PluginReferential plugins = client.getPluginReferential();
verify(reader, times(1)).readString(new URI(BASE_URL), Charsets.UTF_8);
- assertThat(center.getSonar().getVersions()).containsOnly(Version.create("2.2"), Version.create("2.3"));
+ assertThat(plugins.getSonar().getVersions()).containsOnly(Version.create("2.2"), Version.create("2.3"));
assertThat(client.getLastRefreshDate()).isNotNull();
}
@@ -64,16 +69,15 @@ public class UpdateCenterClientTest {
@Test
public void ignore_connection_errors() {
when(reader.readString(any(URI.class), eq(Charsets.UTF_8))).thenThrow(new SonarException());
- assertThat(client.getCenter()).isNull();
+ assertThat(client.getPluginReferential()).isNull();
}
-
@Test
public void cache_data() throws Exception {
when(reader.readString(new URI(BASE_URL), Charsets.UTF_8)).thenReturn("sonar.versions=2.2,2.3");
- client.getCenter();
- client.getCenter();
+ client.getPluginReferential();
+ client.getPluginReferential();
verify(reader, times(1)).readString(new URI(BASE_URL), Charsets.UTF_8);
}
@@ -82,8 +86,8 @@ public class UpdateCenterClientTest {
public void forceRefresh() throws Exception {
when(reader.readString(new URI(BASE_URL), Charsets.UTF_8)).thenReturn("sonar.versions=2.2,2.3");
- client.getCenter();
- client.getCenter(true);
+ client.getPluginReferential();
+ client.getPlugins(true);
verify(reader, times(2)).readString(new URI(BASE_URL), Charsets.UTF_8);
}
diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixTest.java
deleted file mode 100644
index d6b287b7d62..00000000000
--- a/sonar-server/src/test/java/org/sonar/server/plugins/UpdateCenterMatrixTest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.server.plugins;
-
-import org.junit.Before;
-import org.junit.Test;
-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.util.List;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class UpdateCenterMatrixTest {
- private UpdateCenter center;
-
- private Plugin foo;
- private Release foo10;
- private Release foo11;
- private Release foo12;
-
- private Plugin bar;
- private Release bar10;
- private Release bar11;
-
- @Before
- public void initCenter() {
- center = new UpdateCenter();
- foo = new Plugin("foo");
- foo10 = new Release(foo, "1.0").addRequiredSonarVersions("2.1", "2.2").setDownloadUrl("http://server/foo-1.0.jar");
- foo11 = new Release(foo, "1.1").addRequiredSonarVersions("2.1", "2.2", "2.3").setDownloadUrl("http://server/foo-1.1.jar");
- foo12 = new Release(foo, "1.2").addRequiredSonarVersions("2.3").setDownloadUrl("http://server/foo-1.2.jar");
- foo.addRelease(foo10);
- foo.addRelease(foo11);
- foo.addRelease(foo12);
- center.addPlugin(foo);
-
- bar = new Plugin("bar");
- bar10 = new Release(bar, "1.0").addRequiredSonarVersions("2.1", "2.2").setDownloadUrl("http://server/bar-1.0.jar");
- bar11 = new Release(bar, "1.1").addRequiredSonarVersions("2.2.2", "2.3").setDownloadUrl("http://server/bar-1.1.jar");
- bar.addRelease(bar10);
- bar.addRelease(bar11);
- center.addPlugin(bar);
- }
-
- @Test
- public void findPluginUpdates() {
- UpdateCenterMatrix matrix = new UpdateCenterMatrix(center, Version.create("2.1"));
- matrix.registerInstalledPlugin("foo", Version.create("1.0"));
- List<PluginUpdate> updates = matrix.findPluginUpdates();
- assertThat(updates).hasSize(2);
-
- assertThat(updates.get(0).getRelease()).isEqualTo(foo11);
- assertThat(updates.get(0).isCompatible()).isTrue();
-
- assertThat(updates.get(1).getRelease()).isEqualTo(foo12);
- assertThat(updates.get(1).isCompatible()).isFalse();
- assertThat(updates.get(1).requiresSonarUpgrade()).isTrue();
- }
-
- @Test
- public void noPluginUpdatesIfLastReleaseIsInstalled() {
- UpdateCenterMatrix matrix = new UpdateCenterMatrix(center, Version.create("2.3"));
- matrix.registerInstalledPlugin("foo", Version.create("1.2"));
- assertThat(matrix.findPluginUpdates()).isEmpty();
- }
-
- @Test
- public void availablePluginsAreOnlyTheBestReleases() {
- UpdateCenterMatrix matrix = new UpdateCenterMatrix(center, Version.create("2.2"));
- matrix.registerInstalledPlugin("foo", Version.create("1.0"));
-
- List<PluginUpdate> availables = matrix.findAvailablePlugins();
-
- // bar 1.0 is compatible with the installed sonar
- // bar 1.1 requires sonar to be upgraded to 2.2.2 or 2.3
- // => available plugin to install is bar 1.0
- assertThat(availables.size()).isEqualTo(1);
- assertThat(availables.get(0).getRelease()).isEqualTo(bar10);
- assertThat(availables.get(0).isCompatible()).isTrue();
- }
-
- @Test
- public void availablePluginsRequireSonarUpgrade() {
- UpdateCenterMatrix matrix = new UpdateCenterMatrix(center, Version.create("2.2.1"));
- matrix.registerInstalledPlugin("foo", Version.create("1.0"));
-
- List<PluginUpdate> availables = matrix.findAvailablePlugins();
-
- // bar 1.0 is not compatible with the installed sonar
- // bar 1.1 requires sonar to be upgraded to 2.2.2 or 2.3
- // => available plugin to install is bar 1.1
- assertThat(availables.size()).isEqualTo(1);
- assertThat(availables.get(0).getRelease()).isEqualTo(bar11);
- assertThat(availables.get(0).requiresSonarUpgrade()).isTrue();
- }
-
- @Test
- public void findSonarUpdates() {
- center.getSonar().addRelease(Version.create("2.3"));
- center.getSonar().addRelease(Version.create("2.4"));
-
- UpdateCenterMatrix matrix = new UpdateCenterMatrix(center, Version.create("2.2"));
- List<SonarUpdate> updates = matrix.findSonarUpdates();
-
- // no plugins are installed, so both sonar versions are compatible
- assertThat(updates).hasSize(2);
- assertThat(updates.get(0).hasWarnings()).isFalse();
- assertThat(updates.get(1).hasWarnings()).isFalse();
- }
-
- @Test
- public void warningsOnSonarUpdates() {
- center.getSonar().addRelease(Version.create("2.3"));
- center.getSonar().addRelease(Version.create("2.4"));
-
- UpdateCenterMatrix matrix = new UpdateCenterMatrix(center, Version.create("2.2"));
- matrix.registerInstalledPlugin("foo", Version.create("1.0"));
- matrix.registerInstalledPlugin("bar", Version.create("1.0"));
- List<SonarUpdate> updates = matrix.findSonarUpdates();
-
- assertThat(updates).hasSize(2);
-
- // sonar 2.3 supports foo 1.1/1.2 and bar 1.1
- // => 2 plugin upgrades are required
- assertThat(updates.get(0).hasWarnings()).isTrue();
- assertThat(updates.get(0).requiresPluginUpgrades()).isTrue();
- assertThat(updates.get(0).getPluginsToUpgrade()).hasSize(2);
-
- // sonar 2.4 supports no plugins
- assertThat(updates.get(1).hasWarnings()).isTrue();
- assertThat(updates.get(1).isIncompatible()).isTrue();
- assertThat(updates.get(1).getIncompatiblePlugins()).hasSize(2);
- }
-
- @Test
- public void excludePendingDownloadsFromPluginUpdates() {
- UpdateCenterMatrix matrix = new UpdateCenterMatrix(center, Version.create("2.1"));
- matrix.registerInstalledPlugin("foo", Version.create("1.0"));
- matrix.registerPendingPluginsByFilename("foo-1.0.jar");
- List<PluginUpdate> updates = matrix.findPluginUpdates();
- assertThat(updates.size()).isEqualTo(0);
- }
-
- @Test
- public void excludePendingDownloadsFromAvailablePlugins() {
- UpdateCenterMatrix matrix = new UpdateCenterMatrix(center, Version.create("2.1"));
- matrix.registerPendingPluginsByFilename("foo-1.0.jar");
- matrix.registerPendingPluginsByFilename("bar-1.1.jar");
- List<PluginUpdate> updates = matrix.findAvailablePlugins();
- assertThat(updates.size()).isEqualTo(0);
- }
-}