Parcourir la source

SONAR-12351 list plugins with documentation (#1963)

tags/8.0
Jacek il y a 4 ans
Parent
révision
24b51a5660

+ 2
- 1
server/sonar-server/src/main/java/org/sonar/server/plugins/ws/InstalledAction.java Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

@@ -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 Voir le fichier

@@ -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]");


BIN
sonar-core/src/test/resources/org/sonar/core/platform/jar_with_documentation.jar Voir le fichier


Chargement…
Annuler
Enregistrer