@@ -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; | |||
} |
@@ -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 { |
@@ -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()); |
@@ -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()); |
@@ -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))); |
@@ -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; | |||
} |
@@ -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); | |||
} | |||
/** |