From 6e582ed6c46a23140460648d5496bbf759a44914 Mon Sep 17 00:00:00 2001 From: simonbrandhof Date: Mon, 8 Nov 2010 11:25:25 +0000 Subject: [PATCH] SONAR-1879 Plugin keys must only contain letters and digits --- .../sonar/server/plugins/PluginDeployer.java | 2 +- .../sonar-packaging-maven-plugin/pom.xml | 2 +- .../invoker.properties | 1 + .../it/failIfBadlyFormattedPluginKey/pom.xml | 39 ++++++++++++ .../sonar/plugins/sample/SamplePlugin.java | 30 ++++++++++ .../src/it/overridenPluginKey/pom.xml | 39 ++++++++++++ .../sonar/plugins/sample/SamplePlugin.java | 30 ++++++++++ .../src/it/overridenPluginKey/verify.bsh | 23 +++++++ .../mavenplugin/AbstractSonarPluginMojo.java | 6 +- .../mavenplugin/SonarPluginMojo.java | 19 +++++- .../updatecenter/common/PluginKeyUtils.java | 60 ++++++++++++++++--- .../updatecenter/common/PluginManifest.java | 2 +- .../common/PluginKeyUtilsTest.java | 53 +++++++++++++--- tests/integration/reference-plugin/pom.xml | 2 +- 14 files changed, 283 insertions(+), 25 deletions(-) create mode 100644 subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/invoker.properties create mode 100644 subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/pom.xml create mode 100644 subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/src/main/java/org/sonar/plugins/sample/SamplePlugin.java create mode 100644 subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/pom.xml create mode 100644 subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/src/main/java/org/sonar/plugins/sample/SamplePlugin.java create mode 100644 subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/verify.bsh diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java b/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java index afe8c52387b..b78b00cdea2 100644 --- a/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java +++ b/sonar-server/src/main/java/org/sonar/server/plugins/PluginDeployer.java @@ -286,7 +286,7 @@ public final class PluginDeployer implements ServerComponent { try { URLClassLoader pluginClassLoader = URLClassLoader.newInstance(new URL[] { tempFile.toURI().toURL() }, getClass().getClassLoader()); Plugin pluginInstance = (Plugin) pluginClassLoader.loadClass(mainClass).newInstance(); - plugin.setKey(PluginKeyUtils.getPluginKey(pluginInstance.getKey())); + plugin.setKey(PluginKeyUtils.sanitize(pluginInstance.getKey())); plugin.setDescription(pluginInstance.getDescription()); plugin.setName(pluginInstance.getName()); diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/pom.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/pom.xml index 46ef99d0644..159667d3010 100644 --- a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/pom.xml +++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/pom.xml @@ -112,7 +112,7 @@ src/it/settings.xml - 2.3-SNAPSHOT + 2.4-SNAPSHOT diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/invoker.properties b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/invoker.properties new file mode 100644 index 00000000000..c21e972fc6b --- /dev/null +++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/invoker.properties @@ -0,0 +1 @@ +invoker.buildResult = failure diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/pom.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/pom.xml new file mode 100644 index 00000000000..23055892a53 --- /dev/null +++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + org.codehaus.sonar + test + 1.0 + sonar-plugin + Package dependencies + + + + org.codehaus.sonar + sonar-plugin-api + @sonar.version@ + + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + true + + key-with.bad%characters + org.sonar.plugins.sample.SamplePlugin + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.1 + + + + diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/src/main/java/org/sonar/plugins/sample/SamplePlugin.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/src/main/java/org/sonar/plugins/sample/SamplePlugin.java new file mode 100644 index 00000000000..31710c3a0e6 --- /dev/null +++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/failIfBadlyFormattedPluginKey/src/main/java/org/sonar/plugins/sample/SamplePlugin.java @@ -0,0 +1,30 @@ +package org.sonar.plugins.sample; + +import org.sonar.api.Extension; +import org.sonar.api.Plugin; + +import java.util.Collections; +import java.util.List; + +public class SamplePlugin implements Plugin { + public String getKey() { + return "sample"; + } + + public String getName() { + return "My first Sonar plugin"; + } + + public String getDescription() { + return "You shouldn't expect too much from this plugin."; + } + + public List> getExtensions() { + return Collections.emptyList(); + } + + @Override + public String toString() { + return getKey(); + } +} diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/pom.xml b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/pom.xml new file mode 100644 index 00000000000..71741bbcaac --- /dev/null +++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + org.codehaus.sonar + test + 1.0 + sonar-plugin + Package dependencies + + + + org.codehaus.sonar + sonar-plugin-api + @sonar.version@ + + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + true + + newkey + org.sonar.plugins.sample.SamplePlugin + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.1 + + + + diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/src/main/java/org/sonar/plugins/sample/SamplePlugin.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/src/main/java/org/sonar/plugins/sample/SamplePlugin.java new file mode 100644 index 00000000000..31710c3a0e6 --- /dev/null +++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/src/main/java/org/sonar/plugins/sample/SamplePlugin.java @@ -0,0 +1,30 @@ +package org.sonar.plugins.sample; + +import org.sonar.api.Extension; +import org.sonar.api.Plugin; + +import java.util.Collections; +import java.util.List; + +public class SamplePlugin implements Plugin { + public String getKey() { + return "sample"; + } + + public String getName() { + return "My first Sonar plugin"; + } + + public String getDescription() { + return "You shouldn't expect too much from this plugin."; + } + + public List> getExtensions() { + return Collections.emptyList(); + } + + @Override + public String toString() { + return getKey(); + } +} diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/verify.bsh b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/verify.bsh new file mode 100644 index 00000000000..416c8e1f5de --- /dev/null +++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/it/overridenPluginKey/verify.bsh @@ -0,0 +1,23 @@ +import java.io.*; +import java.util.zip.*; +import java.util.jar.Manifest; + +File file = new File( basedir, "target/test-1.0.jar" ); +if ( !file.isFile() ) +{ + throw new FileNotFoundException( "Could not find generated JAR: " + file ); +} + +ZipFile zipFile = new ZipFile(file); +InputStream input = null; +try { + input = zipFile.getInputStream(zipFile.getEntry("META-INF/MANIFEST.MF")); + Manifest manifest = new Manifest(input); + String key = manifest.getMainAttributes().getValue("Plugin-Key"); + if (!key.equals("newkey")) { + throw new Exception("Plugin key is not valid: " + key); + } +} finally { + zipFile.close(); + input.close(); +} diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/AbstractSonarPluginMojo.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/AbstractSonarPluginMojo.java index eda6b943405..2908c45ad92 100644 --- a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/AbstractSonarPluginMojo.java +++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/AbstractSonarPluginMojo.java @@ -98,7 +98,7 @@ public abstract class AbstractSonarPluginMojo extends AbstractMojo { /** * Plugin key. * - * @parameter expression="${sonar.pluginKey}" default-value="${project.artifactId}" + * @parameter expression="${sonar.pluginKey}" */ protected String pluginKey; @@ -173,8 +173,8 @@ public abstract class AbstractSonarPluginMojo extends AbstractMojo { return classifier; } - public String getPluginKey() { - return PluginKeyUtils.getPluginKey(pluginKey); + public String getExplicitPluginKey() { + return pluginKey; } protected final String getPluginClass() { diff --git a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/SonarPluginMojo.java b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/SonarPluginMojo.java index 4f32ae2fc34..494260d139c 100644 --- a/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/SonarPluginMojo.java +++ b/subprojects/sonar-update-center/sonar-packaging-maven-plugin/src/main/java/org/sonar/updatecenter/mavenplugin/SonarPluginMojo.java @@ -39,6 +39,7 @@ import org.apache.maven.shared.dependency.tree.traversal.BuildingDependencyNodeV import org.codehaus.plexus.archiver.jar.JarArchiver; import org.codehaus.plexus.util.FileUtils; import org.sonar.updatecenter.common.FormatUtils; +import org.sonar.updatecenter.common.PluginKeyUtils; import org.sonar.updatecenter.common.PluginManifest; import java.io.File; @@ -144,6 +145,9 @@ public class SonarPluginMojo extends AbstractSonarPluginMojo { private boolean addMavenDescriptor = true; public void execute() throws MojoExecutionException, MojoFailureException { + checkPluginKey(); + checkPluginClass(); + File jarFile = createArchive(); String classifier = getClassifier(); if (classifier != null) { @@ -154,8 +158,6 @@ public class SonarPluginMojo extends AbstractSonarPluginMojo { } public File createArchive() throws MojoExecutionException { - checkPluginClass(); - File jarFile = getJarFile(getOutputDirectory(), getFinalName(), getClassifier()); MavenArchiver archiver = new MavenArchiver(); archiver.setArchiver(jarArchiver); @@ -236,12 +238,25 @@ public class SonarPluginMojo extends AbstractSonarPluginMojo { return null; } + private void checkPluginKey() throws MojoExecutionException { + if ( StringUtils.isNotBlank(getExplicitPluginKey()) && !PluginKeyUtils.isValid(getExplicitPluginKey())) { + throw new MojoExecutionException("Plugin key is badly formatted. Please use ascii letters and digits only. Value: " + getExplicitPluginKey()); + } + } + private void checkPluginClass() throws MojoExecutionException { if ( !new File(getClassesDirectory(), getPluginClass().replace('.', '/') + ".class").exists()) { throw new MojoExecutionException("Error assembling Sonar-plugin: Plugin-Class '" + getPluginClass() + "' not found"); } } + private String getPluginKey() { + if ( StringUtils.isNotBlank(getExplicitPluginKey())) { + return getExplicitPluginKey(); + } + return PluginKeyUtils.sanitize(getProject().getArtifactId()); + } + protected static File getJarFile(File basedir, String finalName, String classifier) { if (classifier == null) { classifier = ""; diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginKeyUtils.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginKeyUtils.java index 3978cac2831..f39c54d7225 100644 --- a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginKeyUtils.java +++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginKeyUtils.java @@ -1,20 +1,62 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ package org.sonar.updatecenter.common; import org.apache.commons.lang.StringUtils; +/** + * @since 0.4 + */ public final class PluginKeyUtils { - public static String getPluginKey(String pluginKey) { - String key = pluginKey; - if (StringUtils.startsWith(pluginKey, "sonar-") && StringUtils.endsWith(pluginKey, "-plugin")) { - key = StringUtils.removeEnd(StringUtils.removeStart(pluginKey, "sonar-"), "-plugin"); - } else if (StringUtils.endsWith(pluginKey, "-sonar-plugin")) { - key = StringUtils.removeEnd(pluginKey, "-sonar-plugin"); + private PluginKeyUtils() { + // only static methods + } + + public static String sanitize(String mavenArtifactId) { + if (mavenArtifactId == null) { + return null; + } + + String key = mavenArtifactId; + if (StringUtils.startsWith(mavenArtifactId, "sonar-") && StringUtils.endsWith(mavenArtifactId, "-plugin")) { + key = StringUtils.removeEnd(StringUtils.removeStart(mavenArtifactId, "sonar-"), "-plugin"); + } else if (StringUtils.endsWith(mavenArtifactId, "-sonar-plugin")) { + key = StringUtils.removeEnd(mavenArtifactId, "-sonar-plugin"); } - return StringUtils.remove(key, "-"); + return keepLettersAndDigits(key); } - private PluginKeyUtils() { + private static String keepLettersAndDigits(String key) { + StringBuilder sb = new StringBuilder(); + for (int index = 0; index < key.length(); index++) { + char character = key.charAt(index); + if (Character.isLetter(character) || Character.isDigit(character)) { + sb.append(character); + } + } + return sb.toString(); + } + + public static boolean isValid(String pluginKey) { + return StringUtils.isNotBlank(pluginKey) && StringUtils.isAlphanumeric(pluginKey); } -} +} \ No newline at end of file diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginManifest.java b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginManifest.java index ed86cf52a96..5fc630a7dd5 100644 --- a/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginManifest.java +++ b/subprojects/sonar-update-center/sonar-update-center-common/src/main/java/org/sonar/updatecenter/common/PluginManifest.java @@ -106,7 +106,7 @@ public final class PluginManifest { private void loadManifest(Manifest manifest) { Attributes attributes = manifest.getMainAttributes(); - this.key = PluginKeyUtils.getPluginKey(attributes.getValue(KEY)); + this.key = PluginKeyUtils.sanitize(attributes.getValue(KEY)); this.mainClass = attributes.getValue(MAIN_CLASS); this.name = attributes.getValue(NAME); this.description = attributes.getValue(DESCRIPTION); diff --git a/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/PluginKeyUtilsTest.java b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/PluginKeyUtilsTest.java index 1e9e646344a..ca3bbc492c0 100644 --- a/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/PluginKeyUtilsTest.java +++ b/subprojects/sonar-update-center/sonar-update-center-common/src/test/java/org/sonar/updatecenter/common/PluginKeyUtilsTest.java @@ -1,3 +1,22 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ package org.sonar.updatecenter.common; import static org.hamcrest.MatcherAssert.assertThat; @@ -8,13 +27,33 @@ import org.junit.Test; public class PluginKeyUtilsTest { @Test - public void shouldExtractCorrectPluginKey() { - assertThat(PluginKeyUtils.getPluginKey("sonar-test-plugin"), is("test")); - assertThat(PluginKeyUtils.getPluginKey("test-sonar-plugin"), is("test")); - assertThat(PluginKeyUtils.getPluginKey("test"), is("test")); + public void shouldSanitizeMavenArtifactId() { + assertThat(PluginKeyUtils.sanitize("sonar-test-plugin"), is("test")); + assertThat(PluginKeyUtils.sanitize("test-sonar-plugin"), is("test")); + assertThat(PluginKeyUtils.sanitize("test"), is("test")); - assertThat(PluginKeyUtils.getPluginKey("sonar-test-foo-plugin"), is("testfoo")); - assertThat(PluginKeyUtils.getPluginKey("test-foo-sonar-plugin"), is("testfoo")); - assertThat(PluginKeyUtils.getPluginKey("test-foo"), is("testfoo")); + assertThat(PluginKeyUtils.sanitize("sonar-test-foo-plugin"), is("testfoo")); + assertThat(PluginKeyUtils.sanitize("test-foo-sonar-plugin"), is("testfoo")); + assertThat(PluginKeyUtils.sanitize("test-foo"), is("testfoo")); + assertThat(PluginKeyUtils.sanitize("keep.only-digits%12345&and*letters"), is("keeponlydigits12345andletters")); + assertThat(PluginKeyUtils.sanitize(" remove whitespaces "), is("removewhitespaces")); + } + + @Test + public void shouldBeValid() { + assertThat(PluginKeyUtils.isValid("foo"), is(true)); + assertThat(PluginKeyUtils.isValid("sonarfooplugin"), is(true)); + assertThat(PluginKeyUtils.isValid("foo6"), is(true)); + assertThat(PluginKeyUtils.isValid("FOO6"), is(true)); + } + + @Test + public void shouldNotBeValid() { + assertThat(PluginKeyUtils.isValid(null), is(false)); + assertThat(PluginKeyUtils.isValid(""), is(false)); + assertThat(PluginKeyUtils.isValid("sonar-foo-plugin"), is(false)); + assertThat(PluginKeyUtils.isValid("foo.bar"), is(false)); + assertThat(PluginKeyUtils.isValid(" nowhitespaces "), is(false)); + assertThat(PluginKeyUtils.isValid("no whitespaces"), is(false)); } } diff --git a/tests/integration/reference-plugin/pom.xml b/tests/integration/reference-plugin/pom.xml index 23058ffcff5..fbe536ac8ac 100644 --- a/tests/integration/reference-plugin/pom.xml +++ b/tests/integration/reference-plugin/pom.xml @@ -92,7 +92,7 @@ org.codehaus.sonar sonar-packaging-maven-plugin - 0.1 + 0.4-SNAPSHOT true itests.ITestsPlugin -- 2.39.5