]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-17081 - Minimal compatibility version should be compared with runtime API version
authorLéo Geoffroy <99647462+leo-geoffroy-sonarsource@users.noreply.github.com>
Fri, 22 Jul 2022 15:40:51 +0000 (17:40 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 22 Jul 2022 20:03:01 +0000 (20:03 +0000)
server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginJarLoader.java
server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/PluginJarLoaderTest.java
sonar-core/src/main/java/org/sonar/core/platform/PluginClassLoader.java
sonar-core/src/main/java/org/sonar/core/platform/PluginInfo.java
sonar-core/src/test/java/org/sonar/core/platform/PluginClassLoaderTest.java
sonar-core/src/test/java/org/sonar/core/platform/PluginInfoTest.java
sonar-plugin-api-impl/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java

index d04845aaf7826b3ad95c67f18cd480adc3ed8391..19d1426508231daa11917066d1dfc8ec04a9b3cf 100644 (file)
@@ -34,11 +34,11 @@ import java.util.function.Function;
 import java.util.stream.Collectors;
 import javax.inject.Inject;
 import org.apache.commons.io.FileUtils;
+import org.sonar.api.SonarRuntime;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.core.platform.PluginInfo;
-import org.sonar.core.platform.SonarQubeVersion;
 import org.sonar.server.platform.ServerFileSystem;
 
 import static java.lang.String.format;
@@ -60,17 +60,17 @@ public class PluginJarLoader {
   private static final String LOAD_ERROR_GENERIC_MESSAGE = "Startup failed: Plugins can't be loaded. See web logs for more information";
 
   private final ServerFileSystem fs;
-  private final SonarQubeVersion sonarQubeVersion;
+  private final SonarRuntime sonarRuntime;
   private final Set<String> blacklistedPluginKeys;
 
   @Inject
-  public PluginJarLoader(ServerFileSystem fs, SonarQubeVersion sonarQubeVersion) {
-    this(fs, sonarQubeVersion, DEFAULT_BLACKLISTED_PLUGINS);
+  public PluginJarLoader(ServerFileSystem fs, SonarRuntime sonarRuntime) {
+    this(fs, sonarRuntime, DEFAULT_BLACKLISTED_PLUGINS);
   }
 
-  PluginJarLoader(ServerFileSystem fs, SonarQubeVersion sonarQubeVersion, Set<String> blacklistedPluginKeys) {
+  PluginJarLoader(ServerFileSystem fs, SonarRuntime sonarRuntime, Set<String> blacklistedPluginKeys) {
     this.fs = fs;
-    this.sonarQubeVersion = sonarQubeVersion;
+    this.sonarRuntime = sonarRuntime;
     this.blacklistedPluginKeys = blacklistedPluginKeys;
   }
 
@@ -211,8 +211,9 @@ public class PluginJarLoader {
       return false;
     }
 
-    if (!info.isCompatibleWith(sonarQubeVersion.get().toString())) {
-      throw MessageException.of(format("Plugin %s [%s] requires at least SonarQube %s", info.getName(), info.getKey(), info.getMinimalSqVersion()));
+    if (!info.isCompatibleWith(sonarRuntime.getApiVersion().toString())) {
+      throw MessageException.of(format("Plugin %s [%s] requires at least Sonar Plugin API version %s (current: %s)",
+        info.getName(), info.getKey(), info.getMinimalSonarPluginApiVersion(), sonarRuntime.getApiVersion()));
     }
     return true;
   }
index c8be970cc3d16c1a6ea5966554478167d659d00b..36ce28aa56f347f88bc00084b50855c08ce066c1 100644 (file)
@@ -35,10 +35,10 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+import org.sonar.api.SonarRuntime;
 import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.core.platform.PluginInfo;
-import org.sonar.core.platform.SonarQubeVersion;
 import org.sonar.server.platform.ServerFileSystem;
 import org.sonar.updatecenter.common.PluginManifest;
 
@@ -56,12 +56,12 @@ public class PluginJarLoaderTest {
 
   private final ServerFileSystem fs = mock(ServerFileSystem.class);
   private final Set<String> blacklisted = new HashSet<>();
-  private final SonarQubeVersion sonarQubeVersion = mock(SonarQubeVersion.class);
-  private final PluginJarLoader underTest = new PluginJarLoader(fs, sonarQubeVersion, blacklisted);
+  private final SonarRuntime sonarRuntime = mock(SonarRuntime.class);
+  private final PluginJarLoader underTest = new PluginJarLoader(fs, sonarRuntime, blacklisted);
 
   @Before
   public void setUp() throws IOException {
-    when(sonarQubeVersion.get()).thenReturn(org.sonar.api.utils.Version.parse("5.2"));
+    when(sonarRuntime.getApiVersion()).thenReturn(org.sonar.api.utils.Version.parse("5.2"));
     when(fs.getDeployedPluginsDir()).thenReturn(temp.newFolder("deployed"));
     when(fs.getDownloadedPluginsDir()).thenReturn(temp.newFolder("downloaded"));
     when(fs.getHomeDir()).thenReturn(temp.newFolder("home"));
@@ -285,12 +285,12 @@ public class PluginJarLoaderTest {
   }
 
   @Test
-  public void fail_if_plugin_does_not_support_sq_version() throws Exception {
-    when(sonarQubeVersion.get()).thenReturn(org.sonar.api.utils.Version.parse("1.0"));
+  public void fail_if_plugin_does_not_support_plugin_api_version() throws Exception {
+    when(sonarRuntime.getApiVersion()).thenReturn(org.sonar.api.utils.Version.parse("1.0"));
     copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
 
     assertThatThrownBy(() -> underTest.loadPlugins())
-      .hasMessage("Plugin Base Plugin [testbase] requires at least SonarQube 4.5.4");
+      .hasMessage("Plugin Base Plugin [testbase] requires at least Sonar Plugin API version 4.5.4 (current: 1.0)");
   }
 
   private static File copyTestPluginTo(String testPluginName, File toDir) throws IOException {
index 75f6f83c074350728bc9404649968e814b6d5622..624218bec58d0c30a708f2afc21002bf3b96d7a5 100644 (file)
@@ -98,8 +98,8 @@ public class PluginClassLoader {
           Loggers.get(getClass()).warn("Plugin {} [{}] uses a child first classloader which is deprecated", info.getName(), info.getKey());
         }
         def.setSelfFirstStrategy(info.isUseChildFirstClassLoader());
-        Version minSqVersion = info.getMinimalSqVersion();
-        boolean compatibilityMode = minSqVersion != null && minSqVersion.compareToIgnoreQualifier(COMPATIBILITY_MODE_MAX_VERSION) < 0;
+        Version minSonarPluginApiVersion = info.getMinimalSonarPluginApiVersion();
+        boolean compatibilityMode = minSonarPluginApiVersion != null && minSonarPluginApiVersion.compareToIgnoreQualifier(COMPATIBILITY_MODE_MAX_VERSION) < 0;
         if (compatibilityMode) {
           Loggers.get(getClass()).warn("API compatibility mode is no longer supported. In case of error, plugin {} [{}] should package its dependencies.",
             info.getName(), info.getKey());
index 6e8dd8463b4785ca56d2bde1995f3e4c65bf4cff..729b22d9e52c635fe59ed30da95bc4e360355757 100644 (file)
@@ -64,7 +64,7 @@ public class PluginInfo implements Comparable<PluginInfo> {
   private String displayVersion;
 
   @CheckForNull
-  private Version minimalSqVersion;
+  private Version minimalSonarPluginApiVersion;
 
   @CheckForNull
   private String description;
@@ -145,8 +145,8 @@ public class PluginInfo implements Comparable<PluginInfo> {
   }
 
   @CheckForNull
-  public Version getMinimalSqVersion() {
-    return minimalSqVersion;
+  public Version getMinimalSonarPluginApiVersion() {
+    return minimalSonarPluginApiVersion;
   }
 
   @CheckForNull
@@ -220,8 +220,8 @@ public class PluginInfo implements Comparable<PluginInfo> {
     return this;
   }
 
-  public PluginInfo setMinimalSqVersion(@Nullable Version v) {
-    this.minimalSqVersion = v;
+  public PluginInfo setMinimalSonarPluginApiVersion(@Nullable Version v) {
+    this.minimalSonarPluginApiVersion = v;
     return this;
   }
 
@@ -300,20 +300,20 @@ public class PluginInfo implements Comparable<PluginInfo> {
   }
 
   /**
-   * Find out if this plugin is compatible with a given version of SonarQube.
-   * The version of SQ must be greater than or equal to the minimal version
+   * Find out if this plugin is compatible with a given version of Sonar Plugin API.
+   * The version of plugin api embedded in SQ must be greater than or equal to the minimal version
    * needed by the plugin.
    */
-  public boolean isCompatibleWith(String runtimeVersion) {
-    if (null == this.minimalSqVersion) {
+  public boolean isCompatibleWith(String runtimePluginApiVersion) {
+    if (null == this.minimalSonarPluginApiVersion) {
       // no constraint defined on the plugin
       return true;
     }
 
-    Version effectiveMin = Version.create(minimalSqVersion.getName()).removeQualifier();
-    Version effectiveVersion = Version.create(runtimeVersion).removeQualifier();
+    Version effectiveMin = Version.create(minimalSonarPluginApiVersion.getName()).removeQualifier();
+    Version effectiveVersion = Version.create(runtimePluginApiVersion).removeQualifier();
 
-    if (runtimeVersion.endsWith("-SNAPSHOT")) {
+    if (runtimePluginApiVersion.endsWith("-SNAPSHOT")) {
       // check only the major and minor versions (two first fields)
       effectiveMin = Version.create(effectiveMin.getMajor() + "." + effectiveMin.getMinor());
     }
@@ -389,9 +389,9 @@ public class PluginInfo implements Comparable<PluginInfo> {
     setOrganizationName(manifest.getOrganization());
     setOrganizationUrl(manifest.getOrganizationUrl());
     setDisplayVersion(manifest.getDisplayVersion());
-    String minSqVersion = manifest.getSonarVersion();
-    if (minSqVersion != null) {
-      setMinimalSqVersion(Version.create(minSqVersion));
+    String minSonarPluginApiVersion = manifest.getSonarVersion();
+    if (minSonarPluginApiVersion != null) {
+      setMinimalSonarPluginApiVersion(Version.create(minSonarPluginApiVersion));
     }
     setHomepageUrl(manifest.getHomepage());
     setIssueTrackerUrl(manifest.getIssueTrackerUrl());
index 538063734527d173dff30eb9abf5102c9b4f32fb..231e022007e504de67b3f3aaa1c68950240a26bf 100644 (file)
@@ -54,7 +54,7 @@ public class PluginClassLoaderTest {
     PluginInfo plugin = new PluginInfo("foo")
       .setJarFile(jarFile)
       .setMainClass("org.foo.FooPlugin")
-      .setMinimalSqVersion(Version.create("5.2"));
+      .setMinimalSonarPluginApiVersion(Version.create("5.2"));
 
     ExplodedPlugin explodedPlugin = createExplodedPlugin(plugin);
     Collection<PluginClassLoaderDef> defs = underTest.defineClassloaders(
@@ -141,7 +141,7 @@ public class PluginClassLoaderTest {
     PluginInfo info = new PluginInfo("foo")
       .setJarFile(jarFile)
       .setMainClass("org.foo.FooPlugin")
-      .setMinimalSqVersion(Version.create("4.5.2"));
+      .setMinimalSonarPluginApiVersion(Version.create("4.5.2"));
 
     Collection<PluginClassLoaderDef> defs = underTest.defineClassloaders(
       ImmutableMap.of("foo", createExplodedPlugin(info)));
index 892000411132fe4b94be443e2fb910ebef3e74a8..9a7ecd05e5854215788c396f0f86b33b22c548a4 100644 (file)
@@ -187,7 +187,7 @@ public class PluginInfoTest {
     assertThat(pluginInfo.getLicense()).isNull();
     assertThat(pluginInfo.getOrganizationName()).isNull();
     assertThat(pluginInfo.getOrganizationUrl()).isNull();
-    assertThat(pluginInfo.getMinimalSqVersion()).isNull();
+    assertThat(pluginInfo.getMinimalSonarPluginApiVersion()).isNull();
     assertThat(pluginInfo.getRequiredPlugins()).isEmpty();
     assertThat(pluginInfo.isSonarLintSupported()).isFalse();
   }
@@ -222,7 +222,7 @@ public class PluginInfoTest {
     assertThat(pluginInfo.getLicense()).isEqualTo("LGPL");
     assertThat(pluginInfo.getOrganizationName()).isEqualTo("SonarSource");
     assertThat(pluginInfo.getOrganizationUrl()).isEqualTo("http://sonarsource.com");
-    assertThat(pluginInfo.getMinimalSqVersion().getName()).isEqualTo("4.5.1");
+    assertThat(pluginInfo.getMinimalSonarPluginApiVersion().getName()).isEqualTo("4.5.1");
     assertThat(pluginInfo.getRequiredPlugins()).extracting("key").containsOnly("java", "pmd");
     assertThat(pluginInfo.isSonarLintSupported()).isTrue();
   }
@@ -272,7 +272,7 @@ public class PluginInfoTest {
 
     assertThat(checkstyleInfo.getName()).isEqualTo("Checkstyle");
     assertThat(checkstyleInfo.getDocumentationPath()).isNull();
-    assertThat(checkstyleInfo.getMinimalSqVersion()).isEqualTo(Version.create("2.8"));
+    assertThat(checkstyleInfo.getMinimalSonarPluginApiVersion()).isEqualTo(Version.create("2.8"));
   }
 
   @Test
@@ -319,7 +319,7 @@ public class PluginInfoTest {
   PluginInfo withMinSqVersion(@Nullable String version) {
     PluginInfo pluginInfo = new PluginInfo("foo");
     if (version != null) {
-      pluginInfo.setMinimalSqVersion(Version.create(version));
+      pluginInfo.setMinimalSonarPluginApiVersion(Version.create(version));
     }
     return pluginInfo;
   }
index 051b567bc54b57e4caba4476e5f80956250a9f8e..7ace1b55449b68d98bf0209e3b0d2a99e15db6c4 100644 (file)
@@ -80,8 +80,8 @@ public class SonarRuntimeImpl implements SonarRuntime {
   /**
    * Create an instance for SonarQube runtime environment.
    */
-  public static SonarRuntime forSonarQube(Version version, SonarQubeSide side, SonarEdition edition) {
-    return new SonarRuntimeImpl(version, SonarProduct.SONARQUBE, side, edition);
+  public static SonarRuntime forSonarQube(Version apiVersion, SonarQubeSide side, SonarEdition edition) {
+    return new SonarRuntimeImpl(apiVersion, SonarProduct.SONARQUBE, side, edition);
   }
 
   /**