rename PluginClassloaderDef#serverExtension to PluginClassloaderDef#privileged to avoid confusion with the ServerExtension class and annotations
rename PluginClassloaderDef to PluginClassLoaderDef (capital L)
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.core.platform;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.sonar.classloader.Mask;
+
+/**
+ * Temporary information about the classLoader to be created for a plugin (or a group of plugins).
+ */
+class PluginClassLoaderDef {
+
+ private final String basePluginKey;
+ private final Map<String, String> mainClassesByPluginKey = new HashMap<>();
+ private final List<File> files = new ArrayList<>();
+ private final Mask mask = new Mask();
+ private boolean selfFirstStrategy = false;
+
+ /**
+ * Compatibility with API classloader as defined before version 5.2
+ */
+ private boolean compatibilityMode = false;
+
+ private boolean privileged = false;
+
+ PluginClassLoaderDef(String basePluginKey) {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(basePluginKey));
+ this.basePluginKey = basePluginKey;
+ }
+
+ String getBasePluginKey() {
+ return basePluginKey;
+ }
+
+ List<File> getFiles() {
+ return files;
+ }
+
+ void addFiles(Collection<File> f) {
+ this.files.addAll(f);
+ }
+
+ Mask getExportMask() {
+ return mask;
+ }
+
+ boolean isSelfFirstStrategy() {
+ return selfFirstStrategy;
+ }
+
+ void setSelfFirstStrategy(boolean selfFirstStrategy) {
+ this.selfFirstStrategy = selfFirstStrategy;
+ }
+
+ Map<String, String> getMainClassesByPluginKey() {
+ return mainClassesByPluginKey;
+ }
+
+ void addMainClass(String pluginKey, @Nullable String mainClass) {
+ if (!Strings.isNullOrEmpty(mainClass)) {
+ mainClassesByPluginKey.put(pluginKey, mainClass);
+ }
+ }
+
+ boolean isCompatibilityMode() {
+ return compatibilityMode;
+ }
+
+ void setCompatibilityMode(boolean b) {
+ this.compatibilityMode = b;
+ }
+
+ boolean isPrivileged() {
+ return privileged;
+ }
+
+ void setPrivileged(boolean privileged) {
+ this.privileged = privileged;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ PluginClassLoaderDef that = (PluginClassLoaderDef) o;
+ return basePluginKey.equals(that.basePluginKey);
+ }
+
+ @Override
+ public int hashCode() {
+ return basePluginKey.hashCode();
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.core.platform;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Nullable;
-import org.sonar.classloader.Mask;
-
-/**
- * Temporary information about the classloader to be created for a plugin (or a group of plugins).
- */
-class PluginClassloaderDef {
-
- private final String basePluginKey;
- private final Map<String, String> mainClassesByPluginKey = new HashMap<>();
- private final List<File> files = new ArrayList<>();
- private final Mask mask = new Mask();
- private boolean selfFirstStrategy = false;
-
- /**
- * Compatibility with API classloader as defined before version 5.2
- */
- private boolean compatibilityMode = false;
-
- private boolean serverExtension = false;
-
- PluginClassloaderDef(String basePluginKey) {
- Preconditions.checkArgument(!Strings.isNullOrEmpty(basePluginKey));
- this.basePluginKey = basePluginKey;
- }
-
- String getBasePluginKey() {
- return basePluginKey;
- }
-
- List<File> getFiles() {
- return files;
- }
-
- void addFiles(Collection<File> f) {
- this.files.addAll(f);
- }
-
- Mask getExportMask() {
- return mask;
- }
-
- boolean isSelfFirstStrategy() {
- return selfFirstStrategy;
- }
-
- void setSelfFirstStrategy(boolean selfFirstStrategy) {
- this.selfFirstStrategy = selfFirstStrategy;
- }
-
- Map<String, String> getMainClassesByPluginKey() {
- return mainClassesByPluginKey;
- }
-
- void addMainClass(String pluginKey, @Nullable String mainClass) {
- if (!Strings.isNullOrEmpty(mainClass)) {
- mainClassesByPluginKey.put(pluginKey, mainClass);
- }
- }
-
- boolean isCompatibilityMode() {
- return compatibilityMode;
- }
-
- void setCompatibilityMode(boolean b) {
- this.compatibilityMode = b;
- }
-
- boolean isServerExtension() {
- return serverExtension;
- }
-
- void setServerExtension(boolean serverExtension) {
- this.serverExtension = serverExtension;
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- PluginClassloaderDef that = (PluginClassloaderDef) o;
- return basePluginKey.equals(that.basePluginKey);
- }
-
- @Override
- public int hashCode() {
- return basePluginKey.hashCode();
- }
-}
/**
* Creates as many classloaders as requested by the input parameter.
*/
- public Map<PluginClassloaderDef, ClassLoader> create(Collection<PluginClassloaderDef> defs) {
+ public Map<PluginClassLoaderDef, ClassLoader> create(Collection<PluginClassLoaderDef> defs) {
+ ClassLoader baseClassLoader = baseClassLoader();
+
ClassloaderBuilder builder = new ClassloaderBuilder();
- builder.newClassloader(API_CLASSLOADER_KEY, baseClassloader());
+ builder.newClassloader(API_CLASSLOADER_KEY, baseClassLoader);
+ builder.setMask(API_CLASSLOADER_KEY, apiMask());
- for (PluginClassloaderDef def : defs) {
- builder.setMask(API_CLASSLOADER_KEY, def.isServerExtension() ? new Mask() : apiMask());
+ for (PluginClassLoaderDef def : defs) {
builder.newClassloader(def.getBasePluginKey());
- builder.setParent(def.getBasePluginKey(), API_CLASSLOADER_KEY, new Mask());
+ if (def.isPrivileged()) {
+ builder.setParent(def.getBasePluginKey(), baseClassLoader, new Mask());
+ } else {
+ builder.setParent(def.getBasePluginKey(), API_CLASSLOADER_KEY, new Mask());
+ }
builder.setLoadingOrder(def.getBasePluginKey(), def.isSelfFirstStrategy() ? SELF_FIRST : PARENT_FIRST);
for (File jar : def.getFiles()) {
builder.addURL(def.getBasePluginKey(), fileToUrl(jar));
/**
* A plugin can export some resources to other plugins
*/
- private void exportResources(PluginClassloaderDef def, ClassloaderBuilder builder, Collection<PluginClassloaderDef> allPlugins) {
+ private void exportResources(PluginClassLoaderDef def, ClassloaderBuilder builder, Collection<PluginClassLoaderDef> allPlugins) {
// export the resources to all other plugins
builder.setExportMask(def.getBasePluginKey(), def.getExportMask());
- for (PluginClassloaderDef other : allPlugins) {
+ for (PluginClassLoaderDef other : allPlugins) {
if (!other.getBasePluginKey().equals(def.getBasePluginKey())) {
builder.addSibling(def.getBasePluginKey(), other.getBasePluginKey(), new Mask());
}
/**
* Builds classloaders and verifies that all of them are correctly defined
*/
- private Map<PluginClassloaderDef, ClassLoader> build(Collection<PluginClassloaderDef> defs, ClassloaderBuilder builder) {
- Map<PluginClassloaderDef, ClassLoader> result = new HashMap<>();
+ private Map<PluginClassLoaderDef, ClassLoader> build(Collection<PluginClassLoaderDef> defs, ClassloaderBuilder builder) {
+ Map<PluginClassLoaderDef, ClassLoader> result = new HashMap<>();
Map<String, ClassLoader> classloadersByBasePluginKey = builder.build();
- for (PluginClassloaderDef def : defs) {
+ for (PluginClassLoaderDef def : defs) {
ClassLoader classloader = classloadersByBasePluginKey.get(def.getBasePluginKey());
if (classloader == null) {
throw new IllegalStateException(String.format("Fail to create classloader for plugin [%s]", def.getBasePluginKey()));
return result;
}
- ClassLoader baseClassloader() {
+ ClassLoader baseClassLoader() {
return getClass().getClassLoader();
}
* Defines the base keys (defined by {@link #basePluginKey(PluginInfo, Map)}) of the plugins which are allowed to
* run a full server extensions.
*/
- private static final Set<String> SYSTEM_EXTENSION_PLUGINS_BASE_KEYS = ImmutableSet.of("views");
+ private static final Set<String> PRIVILEGED_PLUGINS_BASE_KEYS = ImmutableSet.of("views");
public static final Version COMPATIBILITY_MODE_MAX_VERSION = Version.create("5.2");
}
public Map<String, Plugin> load(Map<String, PluginInfo> infoByKeys) {
- Collection<PluginClassloaderDef> defs = defineClassloaders(infoByKeys);
- Map<PluginClassloaderDef, ClassLoader> classloaders = classloaderFactory.create(defs);
+ Collection<PluginClassLoaderDef> defs = defineClassloaders(infoByKeys);
+ Map<PluginClassLoaderDef, ClassLoader> classloaders = classloaderFactory.create(defs);
return instantiatePluginClasses(classloaders);
}
* different than number of plugins.
*/
@VisibleForTesting
- Collection<PluginClassloaderDef> defineClassloaders(Map<String, PluginInfo> infoByKeys) {
- Map<String, PluginClassloaderDef> classloadersByBasePlugin = new HashMap<>();
+ Collection<PluginClassLoaderDef> defineClassloaders(Map<String, PluginInfo> infoByKeys) {
+ Map<String, PluginClassLoaderDef> classloadersByBasePlugin = new HashMap<>();
for (PluginInfo info : infoByKeys.values()) {
String baseKey = basePluginKey(info, infoByKeys);
- PluginClassloaderDef def = classloadersByBasePlugin.get(baseKey);
+ PluginClassLoaderDef def = classloadersByBasePlugin.get(baseKey);
if (def == null) {
- def = new PluginClassloaderDef(baseKey);
+ def = new PluginClassLoaderDef(baseKey);
classloadersByBasePlugin.put(baseKey, def);
}
ExplodedPlugin explodedPlugin = jarExploder.explode(info);
Version minSqVersion = info.getMinimalSqVersion();
boolean compatibilityMode = minSqVersion != null && minSqVersion.compareToIgnoreQualifier(COMPATIBILITY_MODE_MAX_VERSION) < 0;
def.setCompatibilityMode(compatibilityMode);
- def.setServerExtension(isServerExtension(baseKey));
+ def.setPrivileged(isPrivileged(baseKey));
if (compatibilityMode) {
Loggers.get(getClass()).debug("API compatibility mode is enabled on plugin {} [{}] " +
"(built with API lower than {})",
return classloadersByBasePlugin.values();
}
- private static boolean isServerExtension(String basePluginKey) {
- return SYSTEM_EXTENSION_PLUGINS_BASE_KEYS.contains(basePluginKey);
+ private static boolean isPrivileged(String basePluginKey) {
+ return PRIVILEGED_PLUGINS_BASE_KEYS.contains(basePluginKey);
}
/**
* @throws IllegalStateException if at least one plugin can't be correctly loaded
*/
@VisibleForTesting
- Map<String, Plugin> instantiatePluginClasses(Map<PluginClassloaderDef, ClassLoader> classloaders) {
+ Map<String, Plugin> instantiatePluginClasses(Map<PluginClassLoaderDef, ClassLoader> classloaders) {
// instantiate plugins
Map<String, Plugin> instancesByPluginKey = new HashMap<>();
- for (Map.Entry<PluginClassloaderDef, ClassLoader> entry : classloaders.entrySet()) {
- PluginClassloaderDef def = entry.getKey();
+ for (Map.Entry<PluginClassLoaderDef, ClassLoader> entry : classloaders.entrySet()) {
+ PluginClassLoaderDef def = entry.getKey();
ClassLoader classLoader = entry.getValue();
// the same classloader can be used by multiple plugins
public void unload(Collection<Plugin> plugins) {
for (Plugin plugin : plugins) {
ClassLoader classLoader = plugin.getClass().getClassLoader();
- if (classLoader instanceof Closeable && classLoader != classloaderFactory.baseClassloader()) {
+ if (classLoader instanceof Closeable && classLoader != classloaderFactory.baseClassLoader()) {
try {
((Closeable) classLoader).close();
} catch (Exception e) {
@Test
public void create_isolated_classloader() {
- PluginClassloaderDef def = basePluginDef();
- Map<PluginClassloaderDef, ClassLoader> map = factory.create(asList(def));
+ PluginClassLoaderDef def = basePluginDef();
+ Map<PluginClassLoaderDef, ClassLoader> map = factory.create(asList(def));
assertThat(map).containsOnlyKeys(def);
ClassLoader classLoader = map.get(def);
@Test
public void create_classloader_compatible_with_with_old_api_dependencies() {
- PluginClassloaderDef def = basePluginDef();
+ PluginClassLoaderDef def = basePluginDef();
def.setCompatibilityMode(true);
ClassLoader classLoader = factory.create(asList(def)).get(def);
@Test
public void classloader_exports_resources_to_other_classloaders() {
- PluginClassloaderDef baseDef = basePluginDef();
- PluginClassloaderDef dependentDef = dependentPluginDef();
- Map<PluginClassloaderDef, ClassLoader> map = factory.create(asList(baseDef, dependentDef));
+ PluginClassLoaderDef baseDef = basePluginDef();
+ PluginClassLoaderDef dependentDef = dependentPluginDef();
+ Map<PluginClassLoaderDef, ClassLoader> map = factory.create(asList(baseDef, dependentDef));
ClassLoader baseClassloader = map.get(baseDef);
ClassLoader dependentClassloader = map.get(dependentDef);
assertThat(canLoadClass(baseClassloader, BASE_PLUGIN_CLASSNAME)).isTrue();
}
- private static PluginClassloaderDef basePluginDef() {
- PluginClassloaderDef def = new PluginClassloaderDef(BASE_PLUGIN_KEY);
+ private static PluginClassLoaderDef basePluginDef() {
+ PluginClassLoaderDef def = new PluginClassLoaderDef(BASE_PLUGIN_KEY);
def.addMainClass(BASE_PLUGIN_KEY, BASE_PLUGIN_CLASSNAME);
def.getExportMask().addInclusion("org/sonar/plugins/base/api/");
def.addFiles(asList(fakePluginJar("base-plugin/target/base-plugin-0.1-SNAPSHOT.jar")));
return def;
}
- private static PluginClassloaderDef dependentPluginDef() {
- PluginClassloaderDef def = new PluginClassloaderDef(DEPENDENT_PLUGIN_KEY);
+ private static PluginClassLoaderDef dependentPluginDef() {
+ PluginClassLoaderDef def = new PluginClassLoaderDef(DEPENDENT_PLUGIN_KEY);
def.addMainClass(DEPENDENT_PLUGIN_KEY, DEPENDENT_PLUGIN_CLASSNAME);
def.getExportMask().addInclusion("org/sonar/plugins/dependent/api/");
def.addFiles(asList(fakePluginJar("dependent-plugin/target/dependent-plugin-0.1-SNAPSHOT.jar")));
@Test
public void instantiate_plugin_entry_point() {
- PluginClassloaderDef def = new PluginClassloaderDef("fake");
+ PluginClassLoaderDef def = new PluginClassLoaderDef("fake");
def.addMainClass("fake", FakePlugin.class.getName());
Map<String, Plugin> instances = loader.instantiatePluginClasses(ImmutableMap.of(def, getClass().getClassLoader()));
@Test
public void plugin_entry_point_must_be_no_arg_public() {
- PluginClassloaderDef def = new PluginClassloaderDef("fake");
+ PluginClassLoaderDef def = new PluginClassLoaderDef("fake");
def.addMainClass("fake", IncorrectPlugin.class.getName());
try {
.setMainClass("org.foo.FooPlugin")
.setMinimalSqVersion(Version.create("5.2"));
- Collection<PluginClassloaderDef> defs = loader.defineClassloaders(ImmutableMap.of("foo", info));
+ Collection<PluginClassLoaderDef> defs = loader.defineClassloaders(ImmutableMap.of("foo", info));
assertThat(defs).hasSize(1);
- PluginClassloaderDef def = defs.iterator().next();
+ PluginClassLoaderDef def = defs.iterator().next();
assertThat(def.getBasePluginKey()).isEqualTo("foo");
assertThat(def.isSelfFirstStrategy()).isFalse();
assertThat(def.getFiles()).containsOnly(jarFile);
.setMainClass("org.foo.FooPlugin")
.setMinimalSqVersion(Version.create("4.5.2"));
- Collection<PluginClassloaderDef> defs = loader.defineClassloaders(ImmutableMap.of("foo", info));
+ Collection<PluginClassLoaderDef> defs = loader.defineClassloaders(ImmutableMap.of("foo", info));
assertThat(defs.iterator().next().isCompatibilityMode()).isTrue();
}
.setBasePlugin("foo")
.setUseChildFirstClassLoader(true);
- Collection<PluginClassloaderDef> defs = loader.defineClassloaders(ImmutableMap.of(
+ Collection<PluginClassLoaderDef> defs = loader.defineClassloaders(ImmutableMap.of(
base.getKey(), base, extension1.getKey(), extension1, extension2.getKey(), extension2));
assertThat(defs).hasSize(1);
- PluginClassloaderDef def = defs.iterator().next();
+ PluginClassLoaderDef def = defs.iterator().next();
assertThat(def.getBasePluginKey()).isEqualTo("foo");
assertThat(def.isSelfFirstStrategy()).isFalse();
assertThat(def.getFiles()).containsOnly(baseJarFile, extensionJar1, extensionJar2);
public void plugin_is_recognised_as_server_extension_if_key_is_views_and_extends_no_other_plugin_and_runs_in_compatibility_mode() throws IOException {
PluginInfo views = create52PluginInfo("views");
- Collection<PluginClassloaderDef> defs = loader.defineClassloaders(ImmutableMap.of("views", views));
+ Collection<PluginClassLoaderDef> defs = loader.defineClassloaders(ImmutableMap.of("views", views));
- assertThat(defs.iterator().next().isServerExtension()).isTrue();
+ assertThat(defs.iterator().next().isPrivileged()).isTrue();
}
@Test
PluginInfo views = create52PluginInfo("views")
.setBasePlugin("foo");
- Collection<PluginClassloaderDef> defs = loader.defineClassloaders(ImmutableMap.of("foo", foo, "views", views));
+ Collection<PluginClassLoaderDef> defs = loader.defineClassloaders(ImmutableMap.of("foo", foo, "views", views));
assertThat(defs).extracting("compatibilityMode").containsOnly(false, false);
}