]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6517 fix self-first classloaders in plugins
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 12 May 2015 11:40:32 +0000 (13:40 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 12 May 2015 11:40:32 +0000 (13:40 +0200)
sonar-core/src/main/java/org/sonar/core/platform/PluginLoader.java

index 8722703d7f77640d2eb1aa84771d2e0db938d476..ecede3063a6618af3f46a85ade762887e5cbbda5 100644 (file)
@@ -27,7 +27,6 @@ import org.sonar.api.Plugin;
 import org.sonar.api.ServerComponent;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.classloader.ClassloaderBuilder;
-import org.sonar.classloader.ClassloaderBuilder.LoadingOrder;
 
 import java.io.Closeable;
 import java.io.File;
@@ -39,6 +38,7 @@ import java.util.Map;
 import org.sonar.classloader.Mask;
 
 import static java.util.Arrays.asList;
+import static org.sonar.classloader.ClassloaderBuilder.LoadingOrder.PARENT_FIRST;
 import static org.sonar.classloader.ClassloaderBuilder.LoadingOrder.SELF_FIRST;
 
 /**
@@ -59,6 +59,9 @@ public class PluginLoader implements BatchComponent, ServerComponent {
 
   private static final String[] DEFAULT_SHARED_RESOURCES = {"org/sonar/plugins", "com/sonar/plugins", "com/sonarsource/plugins"};
 
+  // 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 PluginExploder exploder;
 
   public PluginLoader(PluginExploder exploder) {
@@ -108,12 +111,14 @@ public class PluginLoader implements BatchComponent, ServerComponent {
    */
   private void buildClassloaders(Collection<ClassloaderDef> defs) {
     ClassloaderBuilder builder = new ClassloaderBuilder();
+    builder.newClassloader(API_CLASSLOADER_KEY, baseClassloader());
     for (ClassloaderDef def : defs) {
       builder
-        .newClassloader(def.getBasePluginKey(), getClass().getClassLoader())
+        .newClassloader(def.getBasePluginKey())
+        .setParent(def.getBasePluginKey(), API_CLASSLOADER_KEY, new Mask())
         // resources to be exported to other plugin classloaders (siblings)
         .setExportMask(def.getBasePluginKey(), def.getMask())
-        .setLoadingOrder(def.getBasePluginKey(), def.isSelfFirstStrategy() ? SELF_FIRST : LoadingOrder.PARENT_FIRST);
+        .setLoadingOrder(def.getBasePluginKey(), def.isSelfFirstStrategy() ? SELF_FIRST : PARENT_FIRST);
       for (File file : def.getFiles()) {
         builder.addURL(def.getBasePluginKey(), fileToUrl(file));
       }
@@ -164,7 +169,7 @@ public class PluginLoader implements BatchComponent, ServerComponent {
   public void unload(Collection<Plugin> plugins) {
     for (Plugin plugin : plugins) {
       ClassLoader classLoader = plugin.getClass().getClassLoader();
-      if (classLoader instanceof Closeable && classLoader != getClass().getClassLoader()) {
+      if (classLoader instanceof Closeable && classLoader != baseClassloader()) {
         try {
           ((Closeable) classLoader).close();
         } catch (Exception e) {
@@ -174,6 +179,10 @@ public class PluginLoader implements BatchComponent, ServerComponent {
     }
   }
 
+  private ClassLoader baseClassloader() {
+    return getClass().getClassLoader();
+  }
+
   /**
    * Get the root key of a tree of plugins. For example if plugin C depends on B, which depends on A, then
    * B and C must be attached to the classloader of A. The method returns A in the three cases.