aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core
diff options
context:
space:
mode:
authorDavid Gageot <david@gageot.net>2012-06-18 11:47:54 +0200
committerDavid Gageot <david@gageot.net>2012-06-18 12:39:50 +0200
commitba7439977f53e5c05f2c6cd52b907f6582a10bde (patch)
tree0d42f95864ec7e82bbdae465144bacc0307d752e /sonar-core
parent923bd083ff22f8bccf8fe3f698b2b82fa3347354 (diff)
downloadsonarqube-ba7439977f53e5c05f2c6cd52b907f6582a10bde.tar.gz
sonarqube-ba7439977f53e5c05f2c6cd52b907f6582a10bde.zip
SONAR-3516 Check minimal sonar version required by installed plugins
Plugin manifest declares the minimal required version of sonar. This version is verified at server startup. It prevents plugins from failing for API incompatibility reasons. Startup fails with a meaningful message.
Diffstat (limited to 'sonar-core')
-rw-r--r--sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java45
-rw-r--r--sonar-core/src/main/java/org/sonar/core/plugins/PluginInstaller.java1
-rw-r--r--sonar-core/src/test/java/org/sonar/core/plugins/DefaultPluginMetadataTest.java92
-rw-r--r--sonar-core/src/test/java/org/sonar/core/plugins/PluginInstallerTest.java77
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/plugins/checkstyle-extension.xml (renamed from sonar-core/src/test/resources/org/sonar/core/plugins/PluginInstallerTest/shouldCopyRuleExtensionsOnServerSide/checkstyle-extension.xml)0
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/plugins/sonar-switch-off-violations-plugin-1.1.jarbin0 -> 12689 bytes
6 files changed, 151 insertions, 64 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java b/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java
index f9f65033cd8..22ff29fadb9 100644
--- a/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java
+++ b/sonar-core/src/main/java/org/sonar/core/plugins/DefaultPluginMetadata.java
@@ -19,6 +19,10 @@
*/
package org.sonar.core.plugins;
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
@@ -35,6 +39,7 @@ public class DefaultPluginMetadata implements PluginMetadata, Comparable<PluginM
private String[] pathsToInternalDeps = new String[0];
private String key;
private String version;
+ private String sonarVersion;
private String name;
private String mainClass;
private String description;
@@ -166,6 +171,46 @@ public class DefaultPluginMetadata implements PluginMetadata, Comparable<PluginM
return this;
}
+ public String getSonarVersion() {
+ return sonarVersion;
+ }
+
+ public DefaultPluginMetadata setSonarVersion(String sonarVersion) {
+ this.sonarVersion = sonarVersion;
+ return this;
+ }
+
+ /**
+ * Find out if this plugin is compatible with a given version of Sonar.
+ * The version of sonar must be greater than or equal to the minimal version
+ * needed by the plugin.
+ *
+ * @param sonarVersion
+ * @return <code>true</code> if the plugin is compatible
+ */
+ public boolean isCompatibleWith(String sonarVersion) {
+ if (null == this.sonarVersion) {
+ return true; // Plugins without sonar version are so old, they are compatible with a version containing this code
+ }
+ if (null == sonarVersion) {
+ return true;
+ }
+
+ return ComparisonChain.start()
+ .compare(part(sonarVersion, 0), part(this.sonarVersion, 0))
+ .compare(part(sonarVersion, 1), part(this.sonarVersion, 1))
+ .compare(part(sonarVersion, 2), part(this.sonarVersion, 2))
+ .result() >= 0;
+ }
+
+ private static int part(String version, int index) {
+ Iterable<String> parts = Splitter.on('.').split(version);
+ String part = Iterables.get(parts, index, "0");
+ String onlyDigits = CharMatcher.DIGIT.retainFrom(part);
+
+ return Integer.parseInt(onlyDigits);
+ }
+
public String getHomepage() {
return homepage;
}
diff --git a/sonar-core/src/main/java/org/sonar/core/plugins/PluginInstaller.java b/sonar-core/src/main/java/org/sonar/core/plugins/PluginInstaller.java
index 5566a0e0ae0..d0289f4a82f 100644
--- a/sonar-core/src/main/java/org/sonar/core/plugins/PluginInstaller.java
+++ b/sonar-core/src/main/java/org/sonar/core/plugins/PluginInstaller.java
@@ -116,6 +116,7 @@ public class PluginInstaller {
metadata.setOrganizationUrl(manifest.getOrganizationUrl());
metadata.setMainClass(manifest.getMainClass());
metadata.setVersion(manifest.getVersion());
+ metadata.setSonarVersion(manifest.getSonarVersion());
metadata.setHomepage(manifest.getHomepage());
metadata.setPathsToInternalDeps(manifest.getDependencies());
metadata.setUseChildFirstClassLoader(manifest.isUseChildFirstClassLoader());
diff --git a/sonar-core/src/test/java/org/sonar/core/plugins/DefaultPluginMetadataTest.java b/sonar-core/src/test/java/org/sonar/core/plugins/DefaultPluginMetadataTest.java
index 27cf28eea34..02053827323 100644
--- a/sonar-core/src/test/java/org/sonar/core/plugins/DefaultPluginMetadataTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/plugins/DefaultPluginMetadataTest.java
@@ -19,15 +19,15 @@
*/
package org.sonar.core.plugins;
-import org.hamcrest.core.Is;
import org.junit.Test;
import org.sonar.api.platform.PluginMetadata;
import java.io.File;
import java.util.Arrays;
+import java.util.List;
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.assertThat;
+import static com.google.common.collect.Ordering.natural;
+import static org.fest.assertions.Assertions.assertThat;
public class DefaultPluginMetadataTest {
@@ -41,19 +41,25 @@ public class DefaultPluginMetadataTest {
.setMainClass("org.Main")
.setOrganization("SonarSource")
.setOrganizationUrl("http://sonarsource.org")
- .setVersion("1.1");
-
- assertThat(metadata.getKey(), Is.is("checkstyle"));
- assertThat(metadata.getLicense(), Is.is("LGPL"));
- assertThat(metadata.getDescription(), Is.is("description"));
- assertThat(metadata.getHomepage(), Is.is("http://home"));
- assertThat(metadata.getMainClass(), Is.is("org.Main"));
- assertThat(metadata.getOrganization(), Is.is("SonarSource"));
- assertThat(metadata.getOrganizationUrl(), Is.is("http://sonarsource.org"));
- assertThat(metadata.getVersion(), Is.is("1.1"));
- assertThat(metadata.getBasePlugin(), nullValue());
- assertThat(metadata.getFile(), not(nullValue()));
- assertThat(metadata.getDeployedFiles().size(), is(0));
+ .setVersion("1.1")
+ .setSonarVersion("3.0")
+ .setUseChildFirstClassLoader(true)
+ .setCore(false);
+
+ assertThat(metadata.getKey()).isEqualTo("checkstyle");
+ assertThat(metadata.getLicense()).isEqualTo("LGPL");
+ assertThat(metadata.getDescription()).isEqualTo("description");
+ assertThat(metadata.getHomepage()).isEqualTo("http://home");
+ assertThat(metadata.getMainClass()).isEqualTo("org.Main");
+ assertThat(metadata.getOrganization()).isEqualTo("SonarSource");
+ assertThat(metadata.getOrganizationUrl()).isEqualTo("http://sonarsource.org");
+ assertThat(metadata.getVersion()).isEqualTo("1.1");
+ assertThat(metadata.getSonarVersion()).isEqualTo("3.0");
+ assertThat(metadata.isUseChildFirstClassLoader()).isTrue();
+ assertThat(metadata.isCore()).isFalse();
+ assertThat(metadata.getBasePlugin()).isNull();
+ assertThat(metadata.getFile()).isNotNull();
+ assertThat(metadata.getDeployedFiles()).isEmpty();
}
@Test
@@ -61,16 +67,16 @@ public class DefaultPluginMetadataTest {
DefaultPluginMetadata metadata = DefaultPluginMetadata.create(new File("sonar-checkstyle-plugin.jar"))
.addDeployedFile(new File("foo.jar"))
.addDeployedFile(new File("bar.jar"));
- assertThat(metadata.getDeployedFiles().size(), is(2));
+
+ assertThat(metadata.getDeployedFiles()).hasSize(2);
}
@Test
public void testInternalPathToDependencies() {
DefaultPluginMetadata metadata = DefaultPluginMetadata.create(new File("sonar-checkstyle-plugin.jar"))
- .setPathsToInternalDeps(new String[]{"META-INF/lib/commons-lang.jar", "META-INF/lib/commons-io.jar"});
- assertThat(metadata.getPathsToInternalDeps().length, is(2));
- assertThat(metadata.getPathsToInternalDeps()[0], is("META-INF/lib/commons-lang.jar"));
- assertThat(metadata.getPathsToInternalDeps()[1], is("META-INF/lib/commons-io.jar"));
+ .setPathsToInternalDeps(new String[] {"META-INF/lib/commons-lang.jar", "META-INF/lib/commons-io.jar"});
+
+ assertThat(metadata.getPathsToInternalDeps()).containsOnly("META-INF/lib/commons-lang.jar", "META-INF/lib/commons-io.jar");
}
@Test
@@ -78,23 +84,49 @@ public class DefaultPluginMetadataTest {
DefaultPluginMetadata checkstyle = DefaultPluginMetadata.create(new File("sonar-checkstyle-plugin.jar")).setKey("checkstyle");
PluginMetadata pmd = DefaultPluginMetadata.create(new File("sonar-pmd-plugin.jar")).setKey("pmd");
- assertThat(checkstyle.equals(pmd), is(false));
- assertThat(checkstyle.equals(checkstyle), is(true));
- assertThat(checkstyle.equals(DefaultPluginMetadata.create(new File("sonar-checkstyle-plugin.jar")).setKey("checkstyle")), is(true));
+ assertThat(checkstyle).isEqualTo(checkstyle);
+ assertThat(checkstyle).isEqualTo(DefaultPluginMetadata.create(new File("sonar-checkstyle-plugin.jar")).setKey("checkstyle"));
+ assertThat(checkstyle).isNotEqualTo(pmd);
}
@Test
public void shouldCompare() {
- PluginMetadata checkstyle = DefaultPluginMetadata.create(new File("sonar-checkstyle-plugin.jar"))
+ DefaultPluginMetadata checkstyle = DefaultPluginMetadata.create(new File("sonar-checkstyle-plugin.jar"))
.setKey("checkstyle")
.setName("Checkstyle");
- PluginMetadata pmd = DefaultPluginMetadata.create(new File("sonar-pmd-plugin.jar"))
+ DefaultPluginMetadata pmd = DefaultPluginMetadata.create(new File("sonar-pmd-plugin.jar"))
.setKey("pmd")
.setName("PMD");
+ List<DefaultPluginMetadata> plugins = Arrays.asList(pmd, checkstyle);
+
+ assertThat(natural().sortedCopy(plugins)).onProperty("key").containsExactly("checkstyle", "pmd");
+ }
+
+ @Test
+ public void should_check_compatibility_with_sonar_version() {
+ assertThat(pluginWithVersion("1.1").isCompatibleWith("1.1")).isTrue();
+ assertThat(pluginWithVersion("1.1").isCompatibleWith("1.1.0")).isTrue();
+ assertThat(pluginWithVersion("1.0").isCompatibleWith("1.0.0")).isTrue();
+
+ assertThat(pluginWithVersion("1.0").isCompatibleWith("1.1")).isTrue();
+ assertThat(pluginWithVersion("1.1.1").isCompatibleWith("1.1.2")).isTrue();
+ assertThat(pluginWithVersion("2.0").isCompatibleWith("2.1.0")).isTrue();
+
+ assertThat(pluginWithVersion("1.1").isCompatibleWith("1.0")).isFalse();
+ assertThat(pluginWithVersion("2.0.1").isCompatibleWith("2.0.0")).isFalse();
+ assertThat(pluginWithVersion("2.10").isCompatibleWith("2.1")).isFalse();
+ assertThat(pluginWithVersion("10.10").isCompatibleWith("2.2")).isFalse();
+
+ assertThat(pluginWithVersion("1.1-SNAPSHOT").isCompatibleWith("1.0")).isFalse();
+ assertThat(pluginWithVersion("1.1-SNAPSHOT").isCompatibleWith("1.1")).isTrue();
+ assertThat(pluginWithVersion("1.1-SNAPSHOT").isCompatibleWith("1.2")).isTrue();
+ assertThat(pluginWithVersion("1.0.1-SNAPSHOT").isCompatibleWith("1.0")).isFalse();
+
+ assertThat(pluginWithVersion(null).isCompatibleWith("0")).isTrue();
+ assertThat(pluginWithVersion(null).isCompatibleWith("3.1")).isTrue();
+ }
- PluginMetadata[] array = {pmd, checkstyle};
- Arrays.sort(array);
- assertThat(array[0].getKey(), is("checkstyle"));
- assertThat(array[1].getKey(), is("pmd"));
+ static DefaultPluginMetadata pluginWithVersion(String version) {
+ return DefaultPluginMetadata.create(null).setSonarVersion(version);
}
}
diff --git a/sonar-core/src/test/java/org/sonar/core/plugins/PluginInstallerTest.java b/sonar-core/src/test/java/org/sonar/core/plugins/PluginInstallerTest.java
index 9afc9c9de17..e9a893c48be 100644
--- a/sonar-core/src/test/java/org/sonar/core/plugins/PluginInstallerTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/plugins/PluginInstallerTest.java
@@ -20,86 +20,95 @@
package org.sonar.core.plugins;
import org.apache.commons.io.FileUtils;
+import org.junit.ClassRule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertThat;
+import static org.fest.assertions.Assertions.assertThat;
public class PluginInstallerTest {
- private PluginInstaller extractor= new PluginInstaller();
+ private PluginInstaller extractor = new PluginInstaller();
+
+ @ClassRule
+ public static TemporaryFolder temporaryFolder = new TemporaryFolder();
@Test
public void shouldExtractMetadata() {
DefaultPluginMetadata metadata = extractor.extractMetadata(getFile("sonar-checkstyle-plugin-2.8.jar"), true);
- assertThat(metadata.getKey(), is("checkstyle"));
- assertThat(metadata.getBasePlugin(), nullValue());
- assertThat(metadata.getName(), is("Checkstyle"));
- assertThat(metadata.isCore(), is(true));
- assertThat(metadata.getFile().getName(), is("sonar-checkstyle-plugin-2.8.jar"));
+
+ assertThat(metadata.getKey()).isEqualTo("checkstyle");
+ assertThat(metadata.getBasePlugin()).isNull();
+ assertThat(metadata.getName()).isEqualTo("Checkstyle");
+ assertThat(metadata.isCore()).isEqualTo(true);
+ assertThat(metadata.getFile().getName()).isEqualTo("sonar-checkstyle-plugin-2.8.jar");
+ assertThat(metadata.getVersion()).isEqualTo("2.8");
+ }
+
+ @Test
+ public void should_read_sonar_version() {
+ DefaultPluginMetadata metadata = extractor.extractMetadata(getFile("sonar-switch-off-violations-plugin-1.1.jar"), false);
+
+ assertThat(metadata.getVersion()).isEqualTo("1.1");
+ assertThat(metadata.getSonarVersion()).isEqualTo("2.5");
}
@Test
public void shouldExtractDeprecatedMetadata() {
DefaultPluginMetadata metadata = extractor.extractMetadata(getFile("sonar-emma-plugin-0.3.jar"), false);
- assertThat(metadata.getKey(), is("emma"));
- assertThat(metadata.getBasePlugin(), nullValue());
- assertThat(metadata.getName(), is("Emma"));
+
+ assertThat(metadata.getKey()).isEqualTo("emma");
+ assertThat(metadata.getBasePlugin()).isNull();
+ assertThat(metadata.getName()).isEqualTo("Emma");
}
@Test
public void shouldExtractExtensionMetadata() {
DefaultPluginMetadata metadata = extractor.extractMetadata(getFile("sonar-checkstyle-extensions-plugin-0.1-SNAPSHOT.jar"), true);
- assertThat(metadata.getKey(), is("checkstyleextensions"));
- assertThat(metadata.getBasePlugin(), is("checkstyle"));
+
+ assertThat(metadata.getKey()).isEqualTo("checkstyleextensions");
+ assertThat(metadata.getBasePlugin()).isEqualTo("checkstyle");
}
@Test
public void shouldCopyAndExtractDependencies() throws IOException {
- File toDir = new File("target/test-tmp/PluginInstallerTest/shouldCopyAndExtractDependencies");
- FileUtils.forceMkdir(toDir);
- FileUtils.cleanDirectory(toDir);
+ File toDir = temporaryFolder.newFolder();
DefaultPluginMetadata metadata = extractor.install(getFile("sonar-checkstyle-plugin-2.8.jar"), true, null, toDir);
- assertThat(metadata.getKey(), is("checkstyle"));
- assertThat(new File(toDir, "sonar-checkstyle-plugin-2.8.jar").exists(), is(true));
- assertThat(new File(toDir, "META-INF/lib/checkstyle-5.1.jar").exists(), is(true));
+ assertThat(metadata.getKey()).isEqualTo("checkstyle");
+ assertThat(new File(toDir, "sonar-checkstyle-plugin-2.8.jar")).exists();
+ assertThat(new File(toDir, "META-INF/lib/checkstyle-5.1.jar")).exists();
}
@Test
public void shouldExtractOnlyDependencies() throws IOException {
- File toDir = new File("target/test-tmp/PluginInstallerTest/shouldExtractOnlyDependencies");
- FileUtils.forceMkdir(toDir);
- FileUtils.cleanDirectory(toDir);
+ File toDir = temporaryFolder.newFolder();
extractor.install(getFile("sonar-checkstyle-plugin-2.8.jar"), true, null, toDir);
- assertThat(new File(toDir, "sonar-checkstyle-plugin-2.8.jar").exists(), is(true));
- assertThat(new File(toDir, "META-INF/MANIFEST.MF").exists(), is(false));
- assertThat(new File(toDir, "org/sonar/plugins/checkstyle/CheckstyleVersion.class").exists(), is(false));
+ assertThat(new File(toDir, "sonar-checkstyle-plugin-2.8.jar")).exists();
+ assertThat(new File(toDir, "META-INF/MANIFEST.MF")).doesNotExist();
+ assertThat(new File(toDir, "org/sonar/plugins/checkstyle/CheckstyleVersion.class")).doesNotExist();
}
@Test
public void shouldCopyRuleExtensionsOnServerSide() throws IOException {
- File toDir = new File("target/test-tmp/PluginInstallerTest/shouldCopyRuleExtensionsOnServerSide");
- FileUtils.forceMkdir(toDir);
- FileUtils.cleanDirectory(toDir);
+ File toDir = temporaryFolder.newFolder();
DefaultPluginMetadata metadata = DefaultPluginMetadata.create(getFile("sonar-checkstyle-plugin-2.8.jar"))
.setKey("checkstyle")
- .addDeprecatedExtension(getFile("PluginInstallerTest/shouldCopyRuleExtensionsOnServerSide/checkstyle-extension.xml"));
+ .addDeprecatedExtension(getFile("checkstyle-extension.xml"));
extractor.install(metadata, toDir);
- assertThat(new File(toDir, "sonar-checkstyle-plugin-2.8.jar").exists(), is(true));
- assertThat(new File(toDir, "checkstyle-extension.xml").exists(), is(true));
+ assertThat(new File(toDir, "sonar-checkstyle-plugin-2.8.jar")).exists();
+ assertThat(new File(toDir, "checkstyle-extension.xml")).exists();
}
- private File getFile(String filename) {
- return FileUtils.toFile(getClass().getResource("/org/sonar/core/plugins/" + filename));
+ static File getFile(String filename) {
+ return FileUtils.toFile(PluginInstallerTest.class.getResource("/org/sonar/core/plugins/" + filename));
}
}
diff --git a/sonar-core/src/test/resources/org/sonar/core/plugins/PluginInstallerTest/shouldCopyRuleExtensionsOnServerSide/checkstyle-extension.xml b/sonar-core/src/test/resources/org/sonar/core/plugins/checkstyle-extension.xml
index 75a263db3c3..75a263db3c3 100644
--- a/sonar-core/src/test/resources/org/sonar/core/plugins/PluginInstallerTest/shouldCopyRuleExtensionsOnServerSide/checkstyle-extension.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/plugins/checkstyle-extension.xml
diff --git a/sonar-core/src/test/resources/org/sonar/core/plugins/sonar-switch-off-violations-plugin-1.1.jar b/sonar-core/src/test/resources/org/sonar/core/plugins/sonar-switch-off-violations-plugin-1.1.jar
new file mode 100644
index 00000000000..8044dff8988
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/plugins/sonar-switch-off-violations-plugin-1.1.jar
Binary files differ