diff options
27 files changed, 414 insertions, 538 deletions
@@ -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> </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> </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> </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> </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> </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> </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 > </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); - } -} |