package org.sonar.server.plugins.edition;
import java.util.Arrays;
+import org.sonar.core.platform.PluginInfo;
import org.sonar.updatecenter.common.Plugin;
public final class EditionBundledPlugins {
return SONARSOURCE_ORGANIZATION.equalsIgnoreCase(plugin.getOrganization())
&& Arrays.stream(SONARSOURCE_COMMERCIAL_LICENSES).anyMatch(s -> s.equalsIgnoreCase(plugin.getLicense()));
}
+
+ public static boolean isEditionBundled(PluginInfo pluginInfo) {
+ return SONARSOURCE_ORGANIZATION.equalsIgnoreCase(pluginInfo.getOrganizationName())
+ && Arrays.stream(SONARSOURCE_COMMERCIAL_LICENSES).anyMatch(s -> s.equalsIgnoreCase(pluginInfo.getLicense()));
+ }
}
import org.sonar.core.platform.PluginInfo;
import org.sonar.db.plugin.PluginDto;
import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.plugins.edition.EditionBundledPlugins;
import org.sonar.updatecenter.common.Artifact;
import org.sonar.updatecenter.common.Plugin;
import org.sonar.updatecenter.common.PluginUpdate;
json.prop(PROPERTY_LICENSE, pluginInfo.getLicense());
json.prop(PROPERTY_ORGANIZATION_NAME, pluginInfo.getOrganizationName());
json.prop(PROPERTY_ORGANIZATION_URL, pluginInfo.getOrganizationUrl());
+ json.prop(PROPERTY_EDITION_BUNDLED, EditionBundledPlugins.isEditionBundled(pluginInfo));
json.prop(PROPERTY_HOMEPAGE_URL, pluginInfo.getHomepageUrl());
json.prop(PROPERTY_ISSUE_TRACKER_URL, pluginInfo.getIssueTrackerUrl());
json.prop(PROPERTY_IMPLEMENTATION_BUILD, pluginInfo.getImplementationBuild());
"license": "GNU LGPL 3",
"organizationName": "SonarSource",
"organizationUrl": "http://www.sonarsource.com",
+ "editionBundled": false,
"homepageUrl": "https://redirect.sonarsource.com/plugins/scmgit.html",
"issueTrackerUrl": "http://jira.sonarsource.com/browse/SONARSCGIT",
"implementationBuild": "9ce9d330c313c296fab051317cc5ad4b26319e07",
"license": "GNU LGPL 3",
"organizationName": "SonarSource",
"organizationUrl": "http://www.sonarsource.com",
+ "editionBundled": false,
"homepageUrl": "https://redirect.sonarsource.com/plugins/java.html",
"issueTrackerUrl": "http://jira.sonarsource.com/browse/SONARJAVA",
"implementationBuild": "65396a609ddface8b311a6a665aca92a7da694f1",
"license": "GNU LGPL 3",
"organizationName": "SonarSource",
"organizationUrl": "http://www.sonarsource.com",
+ "editionBundled": false,
"homepageUrl": "https://redirect.sonarsource.com/plugins/scmsvn.html",
"issueTrackerUrl": "http://jira.sonarsource.com/browse/SONARSCSVN",
"implementationBuild": "213fc8a8b582ff530b12dd4a59a6512be1071234",
--- /dev/null
+/*
+ * 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.edition;
+
+import java.util.Random;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.updatecenter.common.Plugin;
+
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class EditionBundledPluginsTest {
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private final Random random = new Random();
+
+ @Test
+ public void isEditionBundled_on_Plugin_fails_with_NPE_if_arg_is_null() {
+ expectedException.expect(NullPointerException.class);
+
+ EditionBundledPlugins.isEditionBundled((Plugin) null);
+ }
+
+ @Test
+ public void isEditionBundled_on_Plugin_returns_false_for_SonarSource_and_non_commercial_license() {
+ Plugin plugin = newPlugin(randomizeCase("SonarSource"), randomAlphanumeric(3));
+
+ assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isFalse();
+ }
+
+ @Test
+ public void isEditionBundled_on_Plugin_returns_false_for_license_SonarSource_and_non_SonarSource_organization() {
+ Plugin plugin = newPlugin(randomAlphanumeric(3), randomizeCase("SonarSource"));
+
+ assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isFalse();
+ }
+
+ @Test
+ public void isEditionBundled_on_Plugin_returns_false_for_license_Commercial_and_non_SonarSource_organization() {
+ Plugin plugin = newPlugin(randomAlphanumeric(3), randomizeCase("Commercial"));
+
+ assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isFalse();
+ }
+
+ @Test
+ public void isEditionBundled_on_Plugin_returns_true_for_organization_SonarSource_and_license_SonarSource_case_insensitive() {
+ Plugin plugin = newPlugin(randomizeCase("SonarSource"), randomizeCase("SonarSource"));
+
+ assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isTrue();
+ }
+
+ @Test
+ public void isEditionBundled_on_Plugin_returns_true_for_organization_SonarSource_and_license_Commercial_case_insensitive() {
+ Plugin plugin = newPlugin(randomizeCase("SonarSource"), randomizeCase("Commercial"));
+
+ assertThat(EditionBundledPlugins.isEditionBundled(plugin)).isTrue();
+ }
+
+ @Test
+ public void isEditionBundled_on_PluginInfo_fails_with_NPE_if_arg_is_null() {
+ expectedException.expect(NullPointerException.class);
+
+ EditionBundledPlugins.isEditionBundled((PluginInfo) null);
+ }
+
+ @Test
+ public void isEditionBundled_on_PluginInfo_returns_false_for_SonarSource_and_non_commercial_license() {
+ PluginInfo pluginInfo = newPluginInfo(randomizeCase("SonarSource"), randomAlphanumeric(3));
+
+ assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isFalse();
+ }
+
+ @Test
+ public void isEditionBundled_on_PluginInfo_returns_false_for_license_SonarSource_and_non_SonarSource_organization() {
+ PluginInfo pluginInfo = newPluginInfo(randomAlphanumeric(3), randomizeCase("SonarSource"));
+
+ assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isFalse();
+ }
+
+ @Test
+ public void isEditionBundled_on_PluginInfo_returns_false_for_license_Commercial_and_non_SonarSource_organization() {
+ PluginInfo pluginInfo = newPluginInfo(randomAlphanumeric(3), randomizeCase("Commercial"));
+
+ assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isFalse();
+ }
+
+ @Test
+ public void isEditionBundled_on_PluginInfo_returns_true_for_organization_SonarSource_and_license_SonarSource_case_insensitive() {
+ PluginInfo pluginInfo = newPluginInfo(randomizeCase("SonarSource"), randomizeCase("SonarSource"));
+
+ assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isTrue();
+ }
+
+ @Test
+ public void isEditionBundled_on_PluginINfo_returns_true_for_organization_SonarSource_and_license_Commercial_case_insensitive() {
+ PluginInfo pluginInfo = newPluginInfo(randomizeCase("SonarSource"), randomizeCase("Commercial"));
+
+ assertThat(EditionBundledPlugins.isEditionBundled(pluginInfo)).isTrue();
+ }
+
+ private String randomizeCase(String s) {
+ return s.chars()
+ .map(c -> random.nextBoolean() ? Character.toUpperCase(c) : Character.toLowerCase(c))
+ .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
+ .toString();
+ }
+
+ private PluginInfo newPluginInfo(String organization, String license) {
+ PluginInfo pluginInfo = new PluginInfo(randomAlphanumeric(2));
+ if (random.nextBoolean()) {
+ pluginInfo.setName(randomAlphanumeric(3));
+ }
+ if (random.nextBoolean()) {
+ pluginInfo.setOrganizationUrl(randomAlphanumeric(4));
+ }
+ if (random.nextBoolean()) {
+ pluginInfo.setIssueTrackerUrl(randomAlphanumeric(5));
+ }
+ if (random.nextBoolean()) {
+ pluginInfo.setIssueTrackerUrl(randomAlphanumeric(6));
+ }
+ if (random.nextBoolean()) {
+ pluginInfo.setBasePlugin(randomAlphanumeric(7));
+ }
+ if (random.nextBoolean()) {
+ pluginInfo.setHomepageUrl(randomAlphanumeric(8));
+ }
+ return pluginInfo
+ .setOrganizationName(organization)
+ .setLicense(license);
+ }
+
+ private Plugin newPlugin(String organization, String license) {
+ Plugin plugin = Plugin.factory(randomAlphanumeric(2));
+ if (random.nextBoolean()) {
+ plugin.setName(randomAlphanumeric(3));
+ }
+ if (random.nextBoolean()) {
+ plugin.setOrganizationUrl(randomAlphanumeric(4));
+ }
+ if (random.nextBoolean()) {
+ plugin.setTermsConditionsUrl(randomAlphanumeric(5));
+ }
+ if (random.nextBoolean()) {
+ plugin.setIssueTrackerUrl(randomAlphanumeric(6));
+ }
+ if (random.nextBoolean()) {
+ plugin.setCategory(randomAlphanumeric(7));
+ }
+ if (random.nextBoolean()) {
+ plugin.setHomepageUrl(randomAlphanumeric(8));
+ }
+ return plugin
+ .setLicense(license)
+ .setOrganization(organization);
+ }
+}
package org.sonar.server.plugins.ws;
import com.google.common.base.Optional;
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.io.File;
import java.util.Arrays;
+import java.util.Random;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
import static org.mockito.Mockito.when;
import static org.sonar.test.JsonAssert.assertJson;
+@RunWith(DataProviderRunner.class)
public class InstalledActionTest {
private static final String DUMMY_CONTROLLER_KEY = "dummy";
private static final String JSON_EMPTY_PLUGIN_LIST = "{" +
" \"version\": \"1.0\"," +
" \"license\": \"license_hey\"," +
" \"organizationName\": \"org_name\"," +
- " \"organizationUrl\": \"org_url\"," +
+ " \"organizationUrl\": \"org_url\",\n" +
+ " \"editionBundled\": false," +
" \"homepageUrl\": \"homepage_url\"," +
" \"issueTrackerUrl\": \"issueTracker_url\"," +
" \"implementationBuild\": \"sou_rev_sha1\"," +
" \"category\":\"cat_1\"," +
" \"license\": \"license_hey\"," +
" \"organizationName\": \"org_name\"," +
- " \"organizationUrl\": \"org_url\"," +
+ " \"organizationUrl\": \"org_url\",\n" +
+ " \"editionBundled\": false," +
" \"homepageUrl\": \"homepage_url\"," +
" \"issueTrackerUrl\": \"issueTracker_url\"," +
" \"implementationBuild\": \"sou_rev_sha1\"" +
"}");
}
+ @Test
+ @UseDataProvider("editionBundledLicenseValues")
+ public void commercial_plugins_from_SonarSource_has_flag_editionBundled_true_based_on_jar_info(String license) throws Exception {
+ String jarFilename = getClass().getSimpleName() + "/" + "some.jar";
+ Random random = new Random();
+ String organization = random.nextBoolean() ? "SonarSource" : "SONARSOURCE";
+ String pluginKey = "plugKey";
+ when(pluginRepository.getPluginInfos()).thenReturn(of(
+ new PluginInfo(pluginKey)
+ .setName("plugName")
+ .setVersion(Version.create("1.0"))
+ .setLicense(license)
+ .setOrganizationName(organization)
+ .setImplementationBuild("sou_rev_sha1")
+ .setJarFile(new File(getClass().getResource(jarFilename).toURI()))));
+ db.pluginDbTester().insertPlugin(
+ p -> p.setKee(pluginKey),
+ p -> p.setFileHash("abcdplugKey"),
+ p -> p.setUpdatedAt(111111L));
+ // ensure flag editionBundled is computed from jar info by enabling datacenter with other organization and license values
+ UpdateCenter updateCenter = mock(UpdateCenter.class);
+ when(updateCenterMatrixFactory.getUpdateCenter(false)).thenReturn(Optional.of(updateCenter));
+ when(updateCenter.findAllCompatiblePlugins()).thenReturn(
+ singletonList(
+ Plugin.factory(pluginKey)
+ .setOrganization("foo")
+ .setLicense("bar")
+ .setCategory("cat_1")));
+
+
+ underTest.handle(request, response);
+
+ verifyZeroInteractions(updateCenterMatrixFactory);
+ assertJson(response.outputAsString())
+ .isSimilarTo("{" +
+ " \"plugins\":" +
+ " [" +
+ " {" +
+ " \"key\": \"plugKey\"," +
+ " \"name\": \"plugName\"," +
+ " \"license\": \"" + license + "\"," +
+ " \"organizationName\": \"" + organization + "\"," +
+ " \"editionBundled\": true" +
+ " }" +
+ " ]" +
+ "}");
+ }
+
+ @DataProvider
+ public static Object[][] editionBundledLicenseValues() {
+ return new Object[][] {
+ {"sonarsource"},
+ {"SonarSource"},
+ {"SonaRSOUrce"},
+ {"SONARSOURCE"},
+ {"commercial"},
+ {"Commercial"},
+ {"COMMERCIAL"},
+ {"COmmERCiaL"},
+ };
+ }
+
@Test
public void only_one_plugin_can_have_a_specific_name_and_key() throws Exception {
when(pluginRepository.getPluginInfos()).thenReturn(