*/
package org.sonar.server.plugins;
+import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
import org.codehaus.classworlds.ClassRealm;
import org.codehaus.classworlds.ClassWorld;
import org.codehaus.classworlds.DuplicateRealmException;
+import org.slf4j.LoggerFactory;
import org.sonar.api.ServerComponent;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class PluginClassLoaders implements ServerComponent {
- private Map<String, ClassLoader> classLoaderByPluginKey = new HashMap<String, ClassLoader>();
+ private Map<String, ClassLoader> classLoaderByPluginKey = Maps.newHashMap();
private ClassWorld world = new ClassWorld();
public ClassLoader create(PluginMetadata plugin) {
+ return create(plugin.getKey(), plugin.getDeployedFiles());
+ }
+
+ ClassLoader create(String pluginKey, Collection<File> classloaderFiles) {
try {
ClassRealm realm;
- realm = world.newRealm(plugin.getKey(), getClass().getClassLoader());
- for (File file : plugin.getDeployedFiles()) {
+ realm = world.newRealm(pluginKey, getClass().getClassLoader());
+ for (File file : classloaderFiles) {
realm.addConstituent(toUrl(file));
}
ClassLoader classloader = realm.getClassLoader();
- classLoaderByPluginKey.put(plugin.getKey(), classloader);
+ classLoaderByPluginKey.put(pluginKey, classloader);
return classloader;
} catch (DuplicateRealmException e) {
- throw new RuntimeException("Fail to load the classloader of the plugin: " + plugin, e);
+ throw new RuntimeException("Fail to load the classloader of the plugin: " + pluginKey, e);
} catch (MalformedURLException e) {
- throw new RuntimeException("Fail to load the classloader of the plugin: " + plugin, e);
+ throw new RuntimeException("Fail to load the classloader of the plugin: " + pluginKey, e);
}
}
- private URL toUrl(File file) throws MalformedURLException {
+
+ URL toUrl(File file) throws MalformedURLException {
// From Classworlds javadoc :
// A constituent is a URL that points to either a JAR format file containing
// classes and/or resources, or a directory that should be used for searching.
public ClassLoader getClassLoader(String pluginKey) {
return classLoaderByPluginKey.get(pluginKey);
}
+
+ public Class getClass(String pluginKey, String classname) {
+ Class clazz = null;
+ ClassLoader classloader = classLoaderByPluginKey.get(pluginKey);
+ if (classloader != null) {
+ try {
+ clazz = classloader.loadClass(classname);
+
+ } catch (ClassNotFoundException e) {
+ LoggerFactory.getLogger(getClass()).warn("Class not found in plugin " + pluginKey + ": " + classname, e);
+ }
+ }
+ return clazz;
+ }
}
import org.sonar.server.filters.FilterExecutor;
import org.sonar.server.filters.FilterResult;
import org.sonar.server.platform.Platform;
+import org.sonar.server.plugins.PluginClassLoaders;
import org.sonar.server.plugins.PluginDownloader;
import org.sonar.server.plugins.UpdateFinder;
import org.sonar.server.plugins.UpdateFinderFactory;
public final class JRubyFacade implements ServerComponent {
public FilterResult executeFilter(Filter filter) {
- return getContainer().getComponent(FilterExecutor.class).execute(filter);
+ return getContainer().getComponent(FilterExecutor.class).execute(filter);
}
/* PLUGINS */
public String colorizeCode(String code, String language) {
try {
return getContainer().getComponent(CodeColorizers.class).toHtml(code, language);
-
+
} catch (Exception e) {
LoggerFactory.getLogger(getClass()).error("Can not highlight the code, language= " + language, e);
return code;
}
-
public List<ViewProxy<Widget>> getWidgets(String resourceScope, String resourceQualifier, String resourceLanguage) {
return getContainer().getComponent(Views.class).getWidgets(resourceScope, resourceQualifier, resourceLanguage);
}
}
-
-
/* PROFILES CONSOLE : RULES AND METRIC THRESHOLDS */
public List<RuleRepository> getRuleRepositories() {
return getContainer().getComponent(Configuration.class).getString(key, null);
}
- public Object getComponentByClass(String className) {
+ public Object getCoreComponentByClassname(String className) {
if (className == null) {
return null;
}
}
}
+ public Object getComponentByClassname(String pluginKey, String className) {
+ Object component = null;
+ PicoContainer container = getContainer();
+ Class componentClass = container.getComponent(PluginClassLoaders.class).getClass(pluginKey, className);
+ if (componentClass!=null) {
+ component = container.getComponent(componentClass);
+ }
+ return component;
+ }
+
public PicoContainer getContainer() {
return Platform.getInstance().getContainer();
}
*/
package org.sonar.server.plugins;
+import com.google.common.collect.Lists;
import org.junit.Test;
import org.sonar.test.TestUtils;
assertNotNull(classloader.getResource("foo.txt"));
}
+ @Test
+ public void shouldGetClassByName() throws IOException {
+ File jar = getFile("sonar-build-breaker-plugin-0.1.jar");
+
+ PluginClassLoaders classloaders = new PluginClassLoaders();
+ classloaders.create("build-breaker", Lists.<File>newArrayList(jar));
+
+ assertNotNull(classloaders.getClass("build-breaker", "org.sonar.plugins.buildbreaker.BuildBreakerPlugin"));
+ assertNull(classloaders.getClass("build-breaker", "org.sonar.plugins.buildbreaker.Unknown"));
+ assertNull(classloaders.getClass("unknown", "org.sonar.plugins.buildbreaker.BuildBreakerPlugin"));
+ }
+
private File getFile(String filename) {
return TestUtils.getResource(PluginClassLoadersTest.class, filename);
}