org.sonar.server.plugins.ws.PluginWSCommons.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.server.plugins.ws.PluginWSCommons.java

Source

/*
 * SonarQube
 * Copyright (C) 2009-2017 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * 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  02110-1301, USA.
 */
package org.sonar.server.plugins.ws;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.platform.PluginInfo;
import org.sonar.server.plugins.UpdateCenterMatrixFactory;
import org.sonar.updatecenter.common.Artifact;
import org.sonar.updatecenter.common.Plugin;
import org.sonar.updatecenter.common.PluginUpdate;
import org.sonar.updatecenter.common.Release;
import org.sonar.updatecenter.common.UpdateCenter;
import org.sonar.updatecenter.common.Version;

import static com.google.common.collect.ImmutableSortedSet.copyOf;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static java.lang.String.CASE_INSENSITIVE_ORDER;
import static org.apache.commons.lang.StringUtils.isNotBlank;

public class PluginWSCommons {
    static final String PROPERTY_KEY = "key";
    static final String PROPERTY_NAME = "name";
    static final String PROPERTY_DESCRIPTION = "description";
    static final String PROPERTY_LICENSE = "license";
    static final String PROPERTY_VERSION = "version";
    static final String PROPERTY_CATEGORY = "category";
    static final String PROPERTY_ORGANIZATION_NAME = "organizationName";
    static final String PROPERTY_ORGANIZATION_URL = "organizationUrl";
    static final String PROPERTY_DATE = "date";
    static final String PROPERTY_STATUS = "status";
    static final String PROPERTY_HOMEPAGE_URL = "homepageUrl";
    static final String PROPERTY_ISSUE_TRACKER_URL = "issueTrackerUrl";
    static final String OBJECT_ARTIFACT = "artifact";
    static final String PROPERTY_URL = "url";
    static final String PROPERTY_TERMS_AND_CONDITIONS_URL = "termsAndConditionsUrl";
    static final String OBJECT_UPDATE = "update";
    static final String OBJECT_RELEASE = "release";
    static final String ARRAY_REQUIRES = "requires";
    static final String PROPERTY_UPDATE_CENTER_REFRESH = "updateCenterRefresh";
    static final String PROPERTY_IMPLEMENTATION_BUILD = "implementationBuild";
    static final String PROPERTY_CHANGE_LOG_URL = "changeLogUrl";

    public static final Ordering<PluginInfo> NAME_KEY_PLUGIN_METADATA_COMPARATOR = Ordering.natural()
            .onResultOf(PluginInfo::getName).compound(Ordering.natural().onResultOf(PluginInfo::getKey));
    public static final Comparator<Plugin> NAME_KEY_PLUGIN_ORDERING = Ordering.from(CASE_INSENSITIVE_ORDER)
            .onResultOf(PluginToName.INSTANCE)
            .compound(Ordering.from(CASE_INSENSITIVE_ORDER).onResultOf(PluginToKeyFunction.INSTANCE));
    public static final Comparator<PluginUpdate> NAME_KEY_PLUGIN_UPDATE_ORDERING = Ordering
            .from(NAME_KEY_PLUGIN_ORDERING).onResultOf(PluginUpdateToPlugin.INSTANCE);

    void writePluginInfo(JsonWriter json, PluginInfo pluginInfo, @Nullable String category) {
        json.beginObject();

        json.prop(PROPERTY_KEY, pluginInfo.getKey());
        json.prop(PROPERTY_NAME, pluginInfo.getName());
        json.prop(PROPERTY_DESCRIPTION, pluginInfo.getDescription());
        Version version = pluginInfo.getVersion();
        if (version != null) {
            String functionalVersion = isNotBlank(pluginInfo.getDisplayVersion()) ? pluginInfo.getDisplayVersion()
                    : version.getName();
            json.prop(PROPERTY_VERSION, functionalVersion);
        }
        json.prop(PROPERTY_CATEGORY, category);
        json.prop(PROPERTY_LICENSE, pluginInfo.getLicense());
        json.prop(PROPERTY_ORGANIZATION_NAME, pluginInfo.getOrganizationName());
        json.prop(PROPERTY_ORGANIZATION_URL, pluginInfo.getOrganizationUrl());
        json.prop(PROPERTY_HOMEPAGE_URL, pluginInfo.getHomepageUrl());
        json.prop(PROPERTY_ISSUE_TRACKER_URL, pluginInfo.getIssueTrackerUrl());
        json.prop(PROPERTY_IMPLEMENTATION_BUILD, pluginInfo.getImplementationBuild());

        json.endObject();
    }

    public void writePluginInfoList(JsonWriter json, Iterable<PluginInfo> plugins,
            Map<String, Plugin> compatiblePluginsByKey, String propertyName) {
        json.name(propertyName);
        json.beginArray();
        for (PluginInfo pluginInfo : copyOf(NAME_KEY_PLUGIN_METADATA_COMPARATOR, plugins)) {
            Plugin plugin = compatiblePluginsByKey.get(pluginInfo.getKey());
            writePluginInfo(json, pluginInfo, categoryOrNull(plugin));
        }
        json.endArray();
    }

    public void writePlugin(JsonWriter jsonWriter, Plugin plugin) {
        jsonWriter.prop(PROPERTY_KEY, plugin.getKey());
        jsonWriter.prop(PROPERTY_NAME, plugin.getName());
        jsonWriter.prop(PROPERTY_CATEGORY, plugin.getCategory());
        jsonWriter.prop(PROPERTY_DESCRIPTION, plugin.getDescription());
        jsonWriter.prop(PROPERTY_LICENSE, plugin.getLicense());
        jsonWriter.prop(PROPERTY_TERMS_AND_CONDITIONS_URL, plugin.getTermsConditionsUrl());
        jsonWriter.prop(PROPERTY_ORGANIZATION_NAME, plugin.getOrganization());
        jsonWriter.prop(PROPERTY_ORGANIZATION_URL, plugin.getOrganizationUrl());
        jsonWriter.prop(PROPERTY_HOMEPAGE_URL, plugin.getHomepageUrl());
        jsonWriter.prop(PROPERTY_ISSUE_TRACKER_URL, plugin.getIssueTrackerUrl());
    }

    public void writePluginUpdate(JsonWriter json, PluginUpdate pluginUpdate) {
        Plugin plugin = pluginUpdate.getPlugin();

        json.beginObject();
        writePlugin(json, plugin);
        writeRelease(json, pluginUpdate.getRelease());
        writeUpdate(json, pluginUpdate);
        json.endObject();
    }

    public void writeRelease(JsonWriter jsonWriter, Release release) {
        jsonWriter.name(OBJECT_RELEASE).beginObject();

        String version = isNotBlank(release.getDisplayVersion()) ? release.getDisplayVersion()
                : release.getVersion().toString();
        jsonWriter.prop(PROPERTY_VERSION, version);
        jsonWriter.propDate(PROPERTY_DATE, release.getDate());
        jsonWriter.prop(PROPERTY_DESCRIPTION, release.getDescription());
        jsonWriter.prop(PROPERTY_CHANGE_LOG_URL, release.getChangelogUrl());

        jsonWriter.endObject();
    }

    public void writeArtifact(JsonWriter jsonWriter, Release release) {
        jsonWriter.name(OBJECT_ARTIFACT).beginObject();

        jsonWriter.prop(PROPERTY_NAME, release.getFilename());
        jsonWriter.prop(PROPERTY_URL, release.getDownloadUrl());

        jsonWriter.endObject();
    }

    /**
     * Write an "update" object to the specified jsonwriter.
     * <pre>
     * "update": {
     *   "status": "COMPATIBLE",
     *   "requires": [
     *     {
     *       "key": "java",
     *       "name": "Java",
     *       "description": "SonarQube rule engine."
     *     }
     *   ]
     * }
     * </pre>
     */
    public void writeUpdate(JsonWriter jsonWriter, PluginUpdate pluginUpdate) {
        jsonWriter.name(OBJECT_UPDATE).beginObject();

        writeUpdateProperties(jsonWriter, pluginUpdate);

        jsonWriter.endObject();
    }

    /**
     * Write the update properties to the specified jsonwriter.
     * <pre>
     * "status": "COMPATIBLE",
     * "requires": [
     *   {
     *     "key": "java",
     *     "name": "Java",
     *     "description": "SonarQube rule engine."
     *   }
     * ]
     * </pre>
     */
    public void writeUpdateProperties(JsonWriter jsonWriter, PluginUpdate pluginUpdate) {
        jsonWriter.prop(PROPERTY_STATUS, toJSon(pluginUpdate.getStatus()));

        jsonWriter.name(ARRAY_REQUIRES).beginArray();
        Release release = pluginUpdate.getRelease();
        for (Plugin child : filter(transform(release.getOutgoingDependencies(), ReleaseToArtifact.INSTANCE),
                Plugin.class)) {
            jsonWriter.beginObject();
            jsonWriter.prop(PROPERTY_KEY, child.getKey());
            jsonWriter.prop(PROPERTY_NAME, child.getName());
            jsonWriter.prop(PROPERTY_DESCRIPTION, child.getDescription());
            jsonWriter.endObject();
        }
        jsonWriter.endArray();
    }

    @VisibleForTesting
    static String toJSon(PluginUpdate.Status status) {
        switch (status) {
        case COMPATIBLE:
            return "COMPATIBLE";
        case INCOMPATIBLE:
            return "INCOMPATIBLE";
        case REQUIRE_SONAR_UPGRADE:
            return "REQUIRES_SYSTEM_UPGRADE";
        case DEPENDENCIES_REQUIRE_SONAR_UPGRADE:
            return "DEPS_REQUIRE_SYSTEM_UPGRADE";
        default:
            throw new IllegalArgumentException("Unsupported value of PluginUpdate.Status " + status);
        }
    }

    /**
     * Write properties of the specified UpdateCenter to the specified JsonWriter.
     * <pre>
     * "updateCenterRefresh": "2015-04-24T16:08:36+0200"
     * </pre>
     */
    public void writeUpdateCenterProperties(JsonWriter json, Optional<UpdateCenter> updateCenter) {
        if (updateCenter.isPresent()) {
            json.propDateTime(PROPERTY_UPDATE_CENTER_REFRESH, updateCenter.get().getDate());
        }
    }

    enum PluginToKeyFunction implements Function<Plugin, String> {
        INSTANCE;

        @Override
        public String apply(@Nonnull Plugin input) {
            return input.getKey();
        }
    }

    private enum ReleaseToArtifact implements Function<Release, Artifact> {
        INSTANCE;
        @Override
        public Artifact apply(@Nonnull Release input) {
            return input.getArtifact();
        }

    }

    private enum PluginUpdateToPlugin implements Function<PluginUpdate, Plugin> {
        INSTANCE;
        @Override
        public Plugin apply(@Nonnull PluginUpdate input) {
            return input.getPlugin();
        }
    }

    private enum PluginToName implements Function<Plugin, String> {
        INSTANCE;
        @Override
        public String apply(@Nonnull Plugin input) {
            return input.getName();
        }
    }

    @CheckForNull
    static String categoryOrNull(@Nullable Plugin plugin) {
        return plugin != null ? plugin.getCategory() : null;
    }

    private static List<Plugin> compatiblePlugins(UpdateCenterMatrixFactory updateCenterMatrixFactory) {
        Optional<UpdateCenter> updateCenter = updateCenterMatrixFactory.getUpdateCenter(false);
        return updateCenter.isPresent() ? updateCenter.get().findAllCompatiblePlugins()
                : Collections.<Plugin>emptyList();
    }

    static ImmutableMap<String, Plugin> compatiblePluginsByKey(
            UpdateCenterMatrixFactory updateCenterMatrixFactory) {
        List<Plugin> compatiblePlugins = compatiblePlugins(updateCenterMatrixFactory);
        return Maps.uniqueIndex(compatiblePlugins, PluginToKeyFunction.INSTANCE);
    }
}