aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2018-07-05 11:51:17 +0200
committerSonarTech <sonartech@sonarsource.com>2018-09-19 10:54:37 +0200
commitfdf0f2f89300342c932ab23b71c895866c7d4834 (patch)
tree2a8be2a4e5bf3d39e59efbef7ceefa192ee76711 /sonar-core
parent4013c04fad08403ec9feaa406eb69f2e9dc6d745 (diff)
downloadsonarqube-fdf0f2f89300342c932ab23b71c895866c7d4834.tar.gz
sonarqube-fdf0f2f89300342c932ab23b71c895866c7d4834.zip
SONAR-10541, SONAR-10331 Drop compatibility mode and clean plugin classloader
Diffstat (limited to 'sonar-core')
-rw-r--r--sonar-core/build.gradle14
-rw-r--r--sonar-core/src/main/java/org/sonar/core/platform/PluginClassLoaderDef.java13
-rw-r--r--sonar-core/src/main/java/org/sonar/core/platform/PluginClassloaderFactory.java47
-rw-r--r--sonar-core/src/main/java/org/sonar/core/platform/PluginLoader.java9
-rw-r--r--sonar-core/src/test/java/org/sonar/core/platform/PluginClassloaderFactoryTest.java21
-rw-r--r--sonar-core/src/test/java/org/sonar/core/platform/PluginLoaderTest.java52
6 files changed, 31 insertions, 125 deletions
diff --git a/sonar-core/build.gradle b/sonar-core/build.gradle
index a2d0f1bb189..aad84e6dbfe 100644
--- a/sonar-core/build.gradle
+++ b/sonar-core/build.gradle
@@ -4,10 +4,6 @@ sonarqube {
}
}
-configurations {
- includeInResources
-}
-
dependencies {
// please keep list ordered
@@ -24,8 +20,6 @@ dependencies {
compileOnly 'com.google.code.findbugs:jsr305'
- includeInResources project(path: ':sonar-plugin-api-deps', configuration: 'shadow')
-
testCompile 'com.tngtech.java:junit-dataprovider'
testCompile 'junit:junit'
testCompile 'org.assertj:assertj-core'
@@ -36,14 +30,6 @@ dependencies {
testCompileOnly 'com.google.code.findbugs:jsr305'
}
-// sonar-plugin-api.jar is copied into target JAR file
-processResources {
- into('/') {
- from configurations.includeInResources
- rename '(.*)-' + project.version + '-all.jar', '$1.jar'
- }
-}
-
// Used by sonar-db-core to run DB Unit Tests
artifactoryPublish.skip = false
publishing {
diff --git a/sonar-core/src/main/java/org/sonar/core/platform/PluginClassLoaderDef.java b/sonar-core/src/main/java/org/sonar/core/platform/PluginClassLoaderDef.java
index c1c3584b58a..d228ee088bd 100644
--- a/sonar-core/src/main/java/org/sonar/core/platform/PluginClassLoaderDef.java
+++ b/sonar-core/src/main/java/org/sonar/core/platform/PluginClassLoaderDef.java
@@ -41,11 +41,6 @@ class PluginClassLoaderDef {
private final Mask mask = new Mask();
private boolean selfFirstStrategy = false;
- /**
- * Compatibility with API classloader as defined before version 5.2
- */
- private boolean compatibilityMode = false;
-
PluginClassLoaderDef(String basePluginKey) {
Preconditions.checkArgument(!Strings.isNullOrEmpty(basePluginKey));
this.basePluginKey = basePluginKey;
@@ -85,14 +80,6 @@ class PluginClassLoaderDef {
}
}
- boolean isCompatibilityMode() {
- return compatibilityMode;
- }
-
- void setCompatibilityMode(boolean b) {
- this.compatibilityMode = b;
- }
-
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
diff --git a/sonar-core/src/main/java/org/sonar/core/platform/PluginClassloaderFactory.java b/sonar-core/src/main/java/org/sonar/core/platform/PluginClassloaderFactory.java
index 0c69f978a09..bc584778d68 100644
--- a/sonar-core/src/main/java/org/sonar/core/platform/PluginClassloaderFactory.java
+++ b/sonar-core/src/main/java/org/sonar/core/platform/PluginClassloaderFactory.java
@@ -25,11 +25,9 @@ import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-import org.apache.commons.io.FileUtils;
import org.sonar.api.batch.ScannerSide;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.TempFolder;
import org.sonar.classloader.ClassloaderBuilder;
import org.sonar.classloader.Mask;
@@ -40,8 +38,6 @@ import static org.sonar.classloader.ClassloaderBuilder.LoadingOrder.SELF_FIRST;
* Builds the graph of classloaders to be used to instantiate plugins. It deals with:
* <ul>
* <li>isolation of plugins against core classes (except api)</li>
- * <li>backward-compatibility with plugins built for versions of SQ lower than 5.2. At that time
- * API declared transitive dependencies that were automatically available to plugins</li>
* <li>sharing of some packages between plugins</li>
* <li>loading of the libraries embedded in plugin JAR files (directory META-INF/libs)</li>
* </ul>
@@ -54,13 +50,6 @@ public class PluginClassloaderFactory {
// underscores are used to not conflict with plugin keys (if someday a plugin key is "api")
private static final String API_CLASSLOADER_KEY = "_api_";
- private final TempFolder temp;
- private URL compatibilityModeJar;
-
- public PluginClassloaderFactory(TempFolder temp) {
- this.temp = temp;
- }
-
/**
* Creates as many classloaders as requested by the input parameter.
*/
@@ -78,9 +67,6 @@ public class PluginClassloaderFactory {
for (File jar : def.getFiles()) {
builder.addURL(def.getBasePluginKey(), fileToUrl(jar));
}
- if (def.isCompatibilityMode()) {
- builder.addURL(def.getBasePluginKey(), extractCompatibilityModeJar());
- }
exportResources(def, builder, defs);
}
@@ -120,19 +106,6 @@ public class PluginClassloaderFactory {
return getClass().getClassLoader();
}
- private URL extractCompatibilityModeJar() {
- if (compatibilityModeJar == null) {
- File jar = temp.newFile("sonar-plugin-api-deps", "jar");
- try {
- FileUtils.copyURLToFile(getClass().getResource("/sonar-plugin-api-deps.jar"), jar);
- compatibilityModeJar = jar.toURI().toURL();
- } catch (Exception e) {
- throw new IllegalStateException("Can not extract sonar-plugin-api-deps.jar to " + jar.getAbsolutePath(), e);
- }
- }
- return compatibilityModeJar;
- }
-
private static URL fileToUrl(File file) {
try {
return file.toURI().toURL();
@@ -149,31 +122,25 @@ public class PluginClassloaderFactory {
*/
private static Mask apiMask() {
return new Mask()
- .addInclusion("org/sonar/api/")
- .addInclusion("org/sonar/channel/")
+ .addInclusion("org/sonar/api/")
.addInclusion("org/sonar/check/")
- .addInclusion("org/sonar/colorizer/")
- .addInclusion("org/sonar/duplications/")
- .addInclusion("org/sonar/graph/")
- .addInclusion("org/sonar/plugins/emailnotifications/api/")
- .addInclusion("net/sourceforge/pmd/")
- .addInclusion("org/apache/maven/")
.addInclusion("org/codehaus/stax2/")
.addInclusion("org/codehaus/staxmate/")
.addInclusion("com/ctc/wstx/")
.addInclusion("org/slf4j/")
- .addInclusion("javax/servlet/")
// SLF4J bridges. Do not let plugins re-initialize and configure their logging system
.addInclusion("org/apache/commons/logging/")
.addInclusion("org/apache/log4j/")
.addInclusion("ch/qos/logback/")
- // required for internal libs at SonarSource
+ // Exposed by org.sonar.api.server.authentication.IdentityProvider
+ .addInclusion("javax/servlet/")
+
+ // required for some internal SonarSource plugins (billing, orchestrator, ...)
.addInclusion("org/sonar/server/platform/")
- .addInclusion("org/sonar/core/persistence/")
- .addInclusion("org/sonar/core/properties/")
- .addInclusion("org/sonar/server/views/")
+
+ // required for commercial plugins at SonarSource
.addInclusion("com/sonarsource/plugins/license/api/")
// API exclusions
diff --git a/sonar-core/src/main/java/org/sonar/core/platform/PluginLoader.java b/sonar-core/src/main/java/org/sonar/core/platform/PluginLoader.java
index f44a346336e..7b045fe6961 100644
--- a/sonar-core/src/main/java/org/sonar/core/platform/PluginLoader.java
+++ b/sonar-core/src/main/java/org/sonar/core/platform/PluginLoader.java
@@ -50,7 +50,7 @@ public class PluginLoader {
private static final String[] DEFAULT_SHARED_RESOURCES = {"org/sonar/plugins", "com/sonar/plugins", "com/sonarsource/plugins"};
- public static final Version COMPATIBILITY_MODE_MAX_VERSION = Version.create("5.2");
+ private static final Version COMPATIBILITY_MODE_MAX_VERSION = Version.create("5.2");
private final PluginJarExploder jarExploder;
private final PluginClassloaderFactory classloaderFactory;
@@ -96,15 +96,14 @@ public class PluginLoader {
def.setSelfFirstStrategy(info.isUseChildFirstClassLoader());
Version minSqVersion = info.getMinimalSqVersion();
boolean compatibilityMode = minSqVersion != null && minSqVersion.compareToIgnoreQualifier(COMPATIBILITY_MODE_MAX_VERSION) < 0;
- def.setCompatibilityMode(compatibilityMode);
if (compatibilityMode) {
- Loggers.get(getClass()).debug("API compatibility mode is enabled on plugin {} [{}] " +
- "(built with API lower than {})",
- info.getName(), info.getKey(), COMPATIBILITY_MODE_MAX_VERSION);
+ Loggers.get(getClass()).warn("API compatibility mode is no longer supported. In case of error, plugin {} [{}] should package its dependencies.",
+ info.getName(), info.getKey());
}
}
}
return classloadersByBasePlugin.values();
+
}
/**
diff --git a/sonar-core/src/test/java/org/sonar/core/platform/PluginClassloaderFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/platform/PluginClassloaderFactoryTest.java
index 9d825b758af..329a5431d7a 100644
--- a/sonar-core/src/test/java/org/sonar/core/platform/PluginClassloaderFactoryTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/platform/PluginClassloaderFactoryTest.java
@@ -23,10 +23,8 @@ import com.sonarsource.plugins.license.api.FooBar;
import java.io.File;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
-import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.server.rule.RulesDefinition;
-import org.sonar.api.utils.internal.JUnitTempFolder;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
@@ -38,10 +36,7 @@ public class PluginClassloaderFactoryTest {
static final String BASE_PLUGIN_KEY = "base";
static final String DEPENDENT_PLUGIN_KEY = "dependent";
- @Rule
- public JUnitTempFolder temp = new JUnitTempFolder();
-
- PluginClassloaderFactory factory = new PluginClassloaderFactory(temp);
+ PluginClassloaderFactory factory = new PluginClassloaderFactory();
@Test
public void create_isolated_classloader() {
@@ -62,20 +57,6 @@ public class PluginClassloaderFactoryTest {
}
@Test
- public void create_classloader_compatible_with_with_old_api_dependencies() {
- PluginClassLoaderDef def = basePluginDef();
- def.setCompatibilityMode(true);
- ClassLoader classLoader = factory.create(asList(def)).get(def);
-
- // Plugin can access to API and its transitive dependencies as defined in version 5.1.
- // It can not access to core classes though, even if it was possible in previous versions.
- assertThat(canLoadClass(classLoader, RulesDefinition.class.getCanonicalName())).isTrue();
- assertThat(canLoadClass(classLoader, StringUtils.class.getCanonicalName())).isTrue();
- assertThat(canLoadClass(classLoader, BASE_PLUGIN_CLASSNAME)).isTrue();
- assertThat(canLoadClass(classLoader, PluginClassloaderFactory.class.getCanonicalName())).isFalse();
- }
-
- @Test
public void classloader_exports_resources_to_other_classloaders() {
PluginClassLoaderDef baseDef = basePluginDef();
PluginClassLoaderDef dependentDef = dependentPluginDef();
diff --git a/sonar-core/src/test/java/org/sonar/core/platform/PluginLoaderTest.java b/sonar-core/src/test/java/org/sonar/core/platform/PluginLoaderTest.java
index 76a1268f933..2a2ae2c3575 100644
--- a/sonar-core/src/test/java/org/sonar/core/platform/PluginLoaderTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/platform/PluginLoaderTest.java
@@ -21,13 +21,15 @@ package org.sonar.core.platform;
import com.google.common.collect.ImmutableMap;
import java.io.File;
-import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import org.assertj.core.data.MapEntry;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.updatecenter.common.Version;
import static org.assertj.core.api.Assertions.assertThat;
@@ -39,8 +41,11 @@ public class PluginLoaderTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
+ @Rule
+ public LogTester logTester = new LogTester();
+
private PluginClassloaderFactory classloaderFactory = mock(PluginClassloaderFactory.class);
- private PluginLoader loader = new PluginLoader(new FakePluginExploder(), classloaderFactory);
+ private PluginLoader underTest = new PluginLoader(new FakePluginExploder(), classloaderFactory);
@Test
public void define_classloader() throws Exception {
@@ -50,7 +55,7 @@ public class PluginLoaderTest {
.setMainClass("org.foo.FooPlugin")
.setMinimalSqVersion(Version.create("5.2"));
- Collection<PluginClassLoaderDef> defs = loader.defineClassloaders(ImmutableMap.of("foo", info));
+ Collection<PluginClassLoaderDef> defs = underTest.defineClassloaders(ImmutableMap.of("foo", info));
assertThat(defs).hasSize(1);
PluginClassLoaderDef def = defs.iterator().next();
@@ -59,21 +64,6 @@ public class PluginLoaderTest {
assertThat(def.getFiles()).containsOnly(jarFile);
assertThat(def.getMainClassesByPluginKey()).containsOnly(MapEntry.entry("foo", "org.foo.FooPlugin"));
// TODO test mask - require change in sonar-classloader
-
- // built with SQ 5.2+ -> does not need API compatibility mode
- assertThat(def.isCompatibilityMode()).isFalse();
- }
-
- @Test
- public void enable_compatibility_mode_if_plugin_is_built_before_5_2() throws Exception {
- File jarFile = temp.newFile();
- PluginInfo info = new PluginInfo("foo")
- .setJarFile(jarFile)
- .setMainClass("org.foo.FooPlugin")
- .setMinimalSqVersion(Version.create("4.5.2"));
-
- Collection<PluginClassLoaderDef> defs = loader.defineClassloaders(ImmutableMap.of("foo", info));
- assertThat(defs.iterator().next().isCompatibilityMode()).isTrue();
}
/**
@@ -104,7 +94,7 @@ public class PluginLoaderTest {
.setBasePlugin("foo")
.setUseChildFirstClassLoader(true);
- Collection<PluginClassLoaderDef> defs = loader.defineClassloaders(ImmutableMap.of(
+ Collection<PluginClassLoaderDef> defs = underTest.defineClassloaders(ImmutableMap.of(
base.getKey(), base, extension1.getKey(), extension1, extension2.getKey(), extension2));
assertThat(defs).hasSize(1);
@@ -120,22 +110,18 @@ public class PluginLoaderTest {
}
@Test
- public void plugin_is_not_recognised_as_system_extension_if_key_is_governance_and_extends_another_plugin() throws IOException {
- PluginInfo foo = createPluginInfo("foo");
- PluginInfo governance = createPluginInfo("governance")
- .setBasePlugin("foo");
-
- Collection<PluginClassLoaderDef> defs = loader.defineClassloaders(ImmutableMap.of("foo", foo, "governance", governance));
-
- assertThat(defs).extracting("compatibilityMode").containsOnly(false, false);
- }
-
- private PluginInfo createPluginInfo(String pluginKey) throws IOException {
+ public void log_warning_if_plugin_is_built_with_api_5_2_or_lower() throws Exception {
File jarFile = temp.newFile();
- return new PluginInfo(pluginKey)
+ PluginInfo info = new PluginInfo("foo")
.setJarFile(jarFile)
- .setMainClass("org.foo." + pluginKey + "Plugin")
- .setMinimalSqVersion(Version.create("6.6"));
+ .setMainClass("org.foo.FooPlugin")
+ .setMinimalSqVersion(Version.create("4.5.2"));
+
+ Collection<PluginClassLoaderDef> defs = underTest.defineClassloaders(ImmutableMap.of("foo", info));
+ assertThat(defs).extracting(PluginClassLoaderDef::getBasePluginKey).containsExactly("foo");
+
+ List<String> warnings = logTester.logs(LoggerLevel.WARN);
+ assertThat(warnings).contains("API compatibility mode is no longer supported. In case of error, plugin foo [foo] should package its dependencies.");
}
/**