org.sonar.updatecenter.common.UpdateCenter.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.updatecenter.common.UpdateCenter.java

Source

/*
 * SonarSource :: Update Center :: Common
 * Copyright (C) 2010 SonarSource
 * dev@sonar.codehaus.org
 *
 * This program 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
 */
package org.sonar.updatecenter.common;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.updatecenter.common.exception.IncompatiblePluginVersionException;
import org.sonar.updatecenter.common.exception.PluginNotFoundException;

import java.util.Date;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;

import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newHashSet;

public class UpdateCenter {

    private static final Logger LOG = LoggerFactory.getLogger(UpdateCenter.class);
    private PluginReferential updateCenterPluginReferential;
    private PluginReferential installedPluginReferential;
    private Version installedSonarVersion;
    private Date date;
    private Sonar sonar;

    private UpdateCenter(PluginReferential updateCenterPluginReferential, Sonar sonar) {
        this.updateCenterPluginReferential = updateCenterPluginReferential;
        this.sonar = sonar;
        this.installedPluginReferential = PluginReferential.createEmpty();
    }

    public static UpdateCenter create(PluginReferential updateCenterPluginReferential, Sonar sonar) {
        return new UpdateCenter(updateCenterPluginReferential, sonar);
    }

    public PluginReferential getUpdateCenterPluginReferential() {
        return updateCenterPluginReferential;
    }

    public UpdateCenter registerInstalledPlugins(PluginReferential installedPluginReferential) {
        this.installedPluginReferential = installedPluginReferential;
        return this;
    }

    public Sonar getSonar() {
        return sonar;
    }

    public UpdateCenter setInstalledSonarVersion(Version installedSonarVersion) {
        this.installedSonarVersion = installedSonarVersion;
        return this;
    }

    public Date getDate() {
        return date != null ? new Date(date.getTime()) : null;
    }

    public UpdateCenter setDate(Date date) {
        this.date = date != null ? new Date(date.getTime()) : null;
        return this;
    }

    public List<PluginUpdate> findAvailablePlugins() {
        List<PluginUpdate> availables = newArrayList();
        for (Plugin plugin : updateCenterPluginReferential.getPlugins()) {
            if (isInstalled(plugin)) {
                continue;
            }
            Release release = plugin.getLastCompatibleRelease(installedSonarVersion);
            if (release != null) {
                if (release.isMaster()) {
                    try {
                        PluginUpdate pluginUpdate = PluginUpdate.createWithStatus(release,
                                PluginUpdate.Status.COMPATIBLE);
                        pluginUpdate.setDependencies(findInstallablePlugins(plugin.getKey(), release.getVersion()));
                        availables.add(pluginUpdate);
                    } catch (IncompatiblePluginVersionException e) {
                        availables.add(PluginUpdate.createWithStatus(release,
                                PluginUpdate.Status.DEPENDENCIES_REQUIRE_SONAR_UPGRADE));
                    }
                }
            } else {
                release = plugin.getLastCompatibleReleaseIfUpgrade(installedSonarVersion);
                if (release != null && release.isMaster()) {
                    availables
                            .add(PluginUpdate.createWithStatus(release, PluginUpdate.Status.REQUIRE_SONAR_UPGRADE));
                }
            }
        }
        return availables;
    }

    /**
     * Return all plugins with at least one version compatible with SQ. For ecosystems only parent plugin is returned.
     */
    public List<Plugin> findAllCompatiblePlugins() {
        List<Plugin> availables = newArrayList();
        for (Plugin plugin : updateCenterPluginReferential.getPlugins()) {
            Release release = plugin.getLastCompatible(installedSonarVersion);
            if (release != null && release.getParent() == null) {
                availables.add(plugin);
            }
        }
        return availables;
    }

    public List<PluginUpdate> findPluginUpdates() {
        List<PluginUpdate> updates = newArrayList();
        for (Release installedRelease : getInstalledMasterReleases()) {
            try {
                Plugin plugin = findPlugin(installedRelease);
                for (Release nextRelease : plugin.getReleasesGreaterThan(installedRelease.getVersion())) {
                    updates.add(getPluginUpdate(plugin, nextRelease));
                }
            } catch (NoSuchElementException e) {
                // Nothing to do, this plugin is not in the update center, it has been installed manually.
            }
        }
        return updates;
    }

    private PluginUpdate getPluginUpdate(Plugin plugin, Release nextRelease) {
        PluginUpdate pluginUpdate = PluginUpdate.createForPluginRelease(nextRelease, installedSonarVersion);
        try {
            if (pluginUpdate.isCompatible()) {
                pluginUpdate.setDependencies(findInstallablePlugins(plugin.getKey(), nextRelease.getVersion()));
            }
        } catch (IncompatiblePluginVersionException e) {
            pluginUpdate.setStatus(PluginUpdate.Status.DEPENDENCIES_REQUIRE_SONAR_UPGRADE);
        }
        return pluginUpdate;
    }

    /**
     * Return all releases to download (including outgoing dependencies and installed incoming dependencies) to install / update a plugin
     */
    public List<Release> findInstallablePlugins(String pluginKey, Version minimumVersion) {
        Set<Release> installablePlugins = newHashSet();
        Set<Release> checkedPlugins = newHashSet();
        addInstallablePlugins(pluginKey, minimumVersion, installablePlugins, checkedPlugins);
        return newArrayList(installablePlugins);
    }

    private void addInstallablePlugins(String pluginKey, Version minimumVersion, Set<Release> installablePlugins,
            Set<Release> checkedPlugins) {
        try {
            if (!contain(pluginKey, installablePlugins) && !contain(pluginKey, checkedPlugins)) {
                Plugin plugin = updateCenterPluginReferential.findPlugin(pluginKey);
                Release pluginRelease = plugin.getLastCompatibleRelease(installedSonarVersion);
                if (pluginRelease != null) {
                    if (pluginRelease.getVersion().compareTo(minimumVersion) < 0) {
                        throw new IncompatiblePluginVersionException("Plugin " + pluginKey
                                + " is needed to be installed at version greater or equal " + minimumVersion);
                    }
                    addInstallableRelease(pluginRelease, installablePlugins, checkedPlugins);
                }
            }
        } catch (NoSuchElementException e) {
            throw new PluginNotFoundException(
                    "Needed plugin '" + pluginKey + "' version " + minimumVersion + " not found.");
        }
    }

    private void addInstallableRelease(Release pluginRelease, Set<Release> installablePlugins,
            Set<Release> checkedPlugins) {
        addReleaseIfNotAlreadyInstalled(pluginRelease, installablePlugins);
        checkedPlugins.add(pluginRelease);
        for (Release child : pluginRelease.getChildren()) {
            addReleaseIfNotAlreadyInstalled(child, installablePlugins);
        }
        for (Release outgoingDependency : pluginRelease.getOutgoingDependencies()) {
            addInstallablePlugins(outgoingDependency.getArtifact().getKey(), outgoingDependency.getVersion(),
                    installablePlugins, checkedPlugins);
        }
        for (Release incomingDependency : pluginRelease.getIncomingDependencies()) {
            String pluginKey = incomingDependency.getArtifact().getKey();
            if (isInstalled(pluginKey)) {
                addInstallablePlugins(pluginKey, incomingDependency.getVersion(), installablePlugins,
                        checkedPlugins);
            }
        }
    }

    private boolean contain(final String pluginKey, Set<Release> installablePlugins) {
        return Iterables.any(installablePlugins, new Predicate<Release>() {
            public boolean apply(Release input) {
                return input.getKey().equals(pluginKey);
            }
        });
    }

    private void addReleaseIfNotAlreadyInstalled(Release release, Set<Release> installablePlugins) {
        if (!isInstalled(release)) {
            installablePlugins.add(release);
        }
    }

    public List<SonarUpdate> findSonarUpdates() {
        List<SonarUpdate> updates = Lists.newArrayList();
        SortedSet<Release> releases = sonar.getReleasesGreaterThan(installedSonarVersion);
        for (Release release : releases) {
            updates.add(createSonarUpdate(release));
        }
        return updates;
    }

    private SonarUpdate createSonarUpdate(Release sonarRelease) {
        SonarUpdate update = new SonarUpdate(sonarRelease);
        for (Release installedRelease : getInstalledMasterReleases()) {
            try {
                Plugin plugin = findPlugin(installedRelease);
                Release release = plugin.getRelease(installedRelease.getAdjustedVersion());
                if (release.supportSonarVersion(sonarRelease.getVersion())) {
                    update.addCompatiblePlugin(plugin);
                } else {
                    searchCompatiblePluginUpgrade(sonarRelease, update, installedRelease, plugin);
                }
            } catch (NoSuchElementException e) {
                LOG.info("The plugin '" + installedRelease.getArtifact().getKey() + "' version : "
                        + installedRelease.getVersion().getName() + " has not been found on the update center.");
            }
        }
        return update;
    }

    private void searchCompatiblePluginUpgrade(Release sonarRelease, SonarUpdate update, Release installedRelease,
            Plugin plugin) {
        boolean ok = false;
        Release compatibleRelease = null;
        for (Release greaterPluginRelease : plugin.getReleasesGreaterThan(installedRelease.getVersion())) {
            if (greaterPluginRelease.supportSonarVersion(sonarRelease.getVersion())) {
                compatibleRelease = greaterPluginRelease;
                ok = true;
            }
        }
        if (ok) {
            update.addPluginToUpgrade(compatibleRelease);
        } else {
            update.addIncompatiblePlugin(plugin);
        }
    }

    @VisibleForTesting
    PluginReferential getInstalledPluginReferential() {
        return installedPluginReferential;
    }

    private boolean isInstalled(final Release releaseToFind) {
        return installedPluginReferential.doesContainRelease(releaseToFind.getArtifact().getKey(),
                releaseToFind.getVersion());
    }

    private boolean isInstalled(final Plugin plugin) {
        return isInstalled(plugin.getKey());
    }

    private boolean isInstalled(final String pluginKey) {
        return installedPluginReferential.doesContainPlugin(pluginKey);
    }

    private Plugin findPlugin(Release release) {
        String key = release.getArtifact().getKey();
        return updateCenterPluginReferential.findPlugin(key);
    }

    private List<Release> getInstalledMasterReleases() {
        return installedPluginReferential.getLastMasterReleases();
    }

}