Просмотр исходного кода

SONAR-12351 list plugins with documentation (#1963)

tags/8.0
Jacek 4 лет назад
Родитель
Сommit
24b51a5660

+ 2
- 1
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledAction.java Просмотреть файл

@@ -76,7 +76,8 @@ public class InstalledAction implements PluginsWsAction {
new Change("6.6", "The 'fileHash' field is added"),
new Change("6.6", "The 'sonarLintSupported' field is added"),
new Change("6.6", "The 'updatedAt' field is added"),
new Change("7.0", "The fields 'compressedHash' and 'compressedFilename' are added"))
new Change("7.0", "The fields 'compressedHash' and 'compressedFilename' are added"),
new Change("8.0", "The 'documentationPath' field is added"))
.setHandler(this)
.setResponseExample(Resources.getResource(this.getClass(), "example-installed_plugins.json"));


+ 2
- 0
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingAction.java Просмотреть файл

@@ -28,6 +28,7 @@ import java.util.Collection;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
@@ -77,6 +78,7 @@ public class PendingAction implements PluginsWsAction {
.setDescription("Get the list of plugins which will either be installed or removed at the next startup of the SonarQube instance, sorted by plugin name.<br/>" +
"Require 'Administer System' permission.")
.setSince("5.2")
.setChangelog(new Change("8.0", "The 'documentationPath' field is added"))
.setHandler(this)
.setResponseExample(getResource(this.getClass(), "example-pending_plugins.json"));
}

+ 2
- 0
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PluginWSCommons.java Просмотреть файл

@@ -53,6 +53,7 @@ public class PluginWSCommons {
private static final String PROPERTY_NAME = "name";
private static final String PROPERTY_HASH = "hash";
private static final String PROPERTY_FILENAME = "filename";
private static final String PROPERTY_DOCUMENTATION_PATH = "documentationPath";
private static final String PROPERTY_SONARLINT_SUPPORTED = "sonarLintSupported";
private static final String PROPERTY_DESCRIPTION = "description";
private static final String PROPERTY_LICENSE = "license";
@@ -109,6 +110,7 @@ public class PluginWSCommons {
json.prop(PROPERTY_HOMEPAGE_URL, pluginInfo.getHomepageUrl());
json.prop(PROPERTY_ISSUE_TRACKER_URL, pluginInfo.getIssueTrackerUrl());
json.prop(PROPERTY_IMPLEMENTATION_BUILD, pluginInfo.getImplementationBuild());
json.prop(PROPERTY_DOCUMENTATION_PATH, pluginInfo.getDocumentationPath());
if (pluginDto != null) {
json.prop(PROPERTY_UPDATED_AT, pluginDto.getUpdatedAt());
}

+ 2
- 0
server/sonar-server/src/main/resources/org/sonar/server/plugins/ws/example-installed_plugins.json Просмотреть файл

@@ -15,6 +15,7 @@
"filename": "sonar-scm-git-plugin-1.0.jar",
"hash": "abcdef123456",
"sonarLintSupported": false,
"documentationPath": "static/documentation.md",
"updatedAt": 123456789
},
{
@@ -32,6 +33,7 @@
"filename": "sonar-java-plugin-3.0.jar",
"hash": "abcdef123456",
"sonarLintSupported": true,
"documentationPath": "static/documentation.md",
"updatedAt": 123456789
},
{

+ 4
- 2
server/sonar-server/src/main/resources/org/sonar/server/plugins/ws/example-pending_plugins.json Просмотреть файл

@@ -11,7 +11,8 @@
"organizationUrl": "http://www.sonarsource.com",
"homepageUrl": "https://redirect.sonarsource.com/plugins/scmcvs.html",
"issueTrackerUrl": "http://jira.codehaus.org/browse/SONARSCCVS",
"implementationBuild": "f9735104bfa053abc50edad720c79d89a4f5cd72"
"implementationBuild": "f9735104bfa053abc50edad720c79d89a4f5cd72",
"documentationPath": "static/documentation.md"
}
],
"updating": [
@@ -41,7 +42,8 @@
"organizationUrl": "http://www.sonarsource.com",
"homepageUrl": "https://redirect.sonarsource.com/plugins/scmgit.html/sonar-scm-git-plugin",
"issueTrackerUrl": "https://jira.sonarsource.com/browse/SONARSCGIT",
"implementationBuild": "a713dd64daf8719ba4e7f551f9a1966c62690c17"
"implementationBuild": "a713dd64daf8719ba4e7f551f9a1966c62690c17",
"documentationPath": "static/documentation.md"
}
]
}

+ 3
- 1
server/sonar-server/src/test/java/org/sonar/server/plugins/ws/InstalledActionTest.java Просмотреть файл

@@ -197,6 +197,7 @@ public class InstalledActionTest {
.setHomepageUrl("homepage_url")
.setIssueTrackerUrl("issueTracker_url")
.setImplementationBuild("sou_rev_sha1")
.setDocumentationPath("static/documentation.md")
.setSonarLintSupported(true));
when(pluginFileSystem.getInstalledFiles()).thenReturn(singletonList(plugin));

@@ -224,6 +225,7 @@ public class InstalledActionTest {
" \"issueTrackerUrl\": \"issueTracker_url\"," +
" \"implementationBuild\": \"sou_rev_sha1\"," +
" \"sonarLintSupported\": true," +
" \"documentationPath\": \"static/documentation.md\"," +
" \"filename\": \"" + plugin.getLoadedJar().getFile().getName() + "\"," +
" \"hash\": \"" + plugin.getLoadedJar().getMd5() + "\"," +
" \"updatedAt\": 100" +
@@ -376,7 +378,7 @@ public class InstalledActionTest {

@DataProvider
public static Object[][] editionBundledLicenseValues() {
return new Object[][] {
return new Object[][]{
{"sonarsource"},
{"SonarSource"},
{"SonaRSOUrce"},

+ 31
- 1
sonar-core/src/main/java/org/sonar/core/platform/PluginInfo.java Просмотреть файл

@@ -27,12 +27,16 @@ import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.updatecenter.common.PluginManifest;
import org.sonar.updatecenter.common.Version;
@@ -40,6 +44,7 @@ import org.sonar.updatecenter.common.Version;
import static java.util.Objects.requireNonNull;

public class PluginInfo implements Comparable<PluginInfo> {
private static final Logger LOGGER = Loggers.get(PluginInfo.class);

private static final Joiner SLASH_JOINER = Joiner.on(" / ").skipNulls();

@@ -140,6 +145,9 @@ public class PluginInfo implements Comparable<PluginInfo> {
@CheckForNull
private boolean sonarLintSupported;

@CheckForNull
private String documentationPath;

private final Set<RequiredPlugin> requiredPlugins = new HashSet<>();

public PluginInfo(String key) {
@@ -234,6 +242,10 @@ public class PluginInfo implements Comparable<PluginInfo> {
return sonarLintSupported;
}

public String getDocumentationPath() {
return documentationPath;
}

@CheckForNull
public String getBasePlugin() {
return basePlugin;
@@ -263,6 +275,11 @@ public class PluginInfo implements Comparable<PluginInfo> {
return this;
}

public PluginInfo setDocumentationPath(@Nullable String documentationPath) {
this.documentationPath = documentationPath;
return this;
}

/**
* Required
*/
@@ -313,7 +330,7 @@ public class PluginInfo implements Comparable<PluginInfo> {

public PluginInfo setBasePlugin(@Nullable String s) {
if ("l10nen".equals(s)) {
Loggers.get(PluginInfo.class).info("Plugin [{}] defines 'l10nen' as base plugin. " +
LOGGER.info("Plugin [{}] defines 'l10nen' as base plugin. " +
"This metadata can be removed from manifest of l10n plugins since version 5.2.", key);
basePlugin = null;
} else {
@@ -411,6 +428,7 @@ public class PluginInfo implements Comparable<PluginInfo> {
info.setName(manifest.getName());
info.setMainClass(manifest.getMainClass());
info.setVersion(Version.create(manifest.getVersion()));
info.setDocumentationPath(getDocumentationPath(jarFile));

// optional fields
info.setDescription(manifest.getDescription());
@@ -437,4 +455,16 @@ public class PluginInfo implements Comparable<PluginInfo> {
}
return info;
}

private static String getDocumentationPath(File file) {
try (JarFile jarFile = new JarFile(file)) {
return Optional.ofNullable(jarFile.getEntry("static/documentation.md"))
.map(ZipEntry::getName)
.orElse(null);
} catch (IOException e) {
LOGGER.warn("Could not retrieve documentation path from " + file, e);
}
return null;
}

}

+ 15
- 5
sonar-core/src/test/java/org/sonar/core/platform/PluginInfoTest.java Просмотреть файл

@@ -210,7 +210,7 @@ public class PluginInfoTest {
manifest.setOrganization("SonarSource");
manifest.setOrganizationUrl("http://sonarsource.com");
manifest.setIssueTrackerUrl("http://jira.com");
manifest.setRequirePlugins(new String[] {"java:2.0", "pmd:1.3"});
manifest.setRequirePlugins(new String[]{"java:2.0", "pmd:1.3"});
manifest.setSonarLintSupported(true);

File jarFile = temp.newFile();
@@ -237,7 +237,7 @@ public class PluginInfoTest {
manifest.setVersion("1.0");
manifest.setName("Java");
manifest.setMainClass("org.foo.FooPlugin");
manifest.setRequirePlugins(new String[] {"license:" + version});
manifest.setRequirePlugins(new String[]{"license:" + version});

File jarFile = temp.newFile();
PluginInfo pluginInfo = PluginInfo.create(jarFile, manifest);
@@ -252,7 +252,7 @@ public class PluginInfoTest {
manifest.setVersion("1.0");
manifest.setName("Java");
manifest.setMainClass("org.foo.FooPlugin");
manifest.setRequirePlugins(new String[] {"java:2.0", "license:" + version, "pmd:1.3"});
manifest.setRequirePlugins(new String[]{"java:2.0", "license:" + version, "pmd:1.3"});

File jarFile = temp.newFile();
PluginInfo pluginInfo = PluginInfo.create(jarFile, manifest);
@@ -261,7 +261,7 @@ public class PluginInfoTest {

@DataProvider
public static Object[][] licenseVersions() {
return new Object[][] {
return new Object[][]{
{"0.3"},
{"7.2.0.1253"}
};
@@ -273,11 +273,21 @@ public class PluginInfoTest {
PluginInfo checkstyleInfo = PluginInfo.create(checkstyleJar);

assertThat(checkstyleInfo.getName()).isEqualTo("Checkstyle");
assertThat(checkstyleInfo.getDocumentationPath()).isNull();
assertThat(checkstyleInfo.getMinimalSqVersion()).isEqualTo(Version.create("2.8"));
}

@Test
public void test_toString() throws Exception {
public void create_from_file_with_documentation() {
File jarWithDocs = FileUtils.toFile(getClass().getResource("/org/sonar/core/platform/jar_with_documentation.jar"));
PluginInfo checkstyleInfo = PluginInfo.create(jarWithDocs);

assertThat(checkstyleInfo.getDocumentationPath()).isNotBlank();
assertThat(checkstyleInfo.getDocumentationPath()).isEqualTo("static/documentation.md");
}

@Test
public void test_toString() {
PluginInfo pluginInfo = new PluginInfo("java").setVersion(Version.create("1.1"));
assertThat(pluginInfo.toString()).isEqualTo("[java / 1.1]");


Двоичные данные
sonar-core/src/test/resources/org/sonar/core/platform/jar_with_documentation.jar Просмотреть файл


Загрузка…
Отмена
Сохранить