Skip to content

Commit

Permalink
SONAR-6370 isolate plugin classloader from core classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Brandhof committed Jun 5, 2015
1 parent b1a02ef commit 0956511
Show file tree
Hide file tree
Showing 41 changed files with 772 additions and 310 deletions.
20 changes: 12 additions & 8 deletions plugins/sonar-xoo-plugin/pom.xml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -17,24 +17,28 @@
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
</dependency> <version>18.0</version>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.0</version>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-lang</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang</artifactId> <artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.0</version>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.codehaus.sonar</groupId> <groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-plugin-api</artifactId> <artifactId>sonar-plugin-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.SensorContext;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
package org.sonar.xoo.lang; package org.sonar.xoo.lang;


import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.measure.MetricFinder; import org.sonar.api.batch.measure.MetricFinder;
import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.batch.sensor.Sensor;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.SensorContext;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.SensorContext;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.scm.BlameCommand; import org.sonar.api.batch.scm.BlameCommand;
import org.sonar.api.batch.scm.BlameLine; import org.sonar.api.batch.scm.BlameLine;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.sonar.api.batch.DependsUpon; import org.sonar.api.batch.DependsUpon;
import org.sonar.api.batch.fs.FilePredicates; import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.FileSystem;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.sonar.api.batch.DependedUpon; import org.sonar.api.batch.DependedUpon;
import org.sonar.api.batch.fs.FilePredicates; import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.FileSystem;
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
<version>10.0.1</version> <version>17.0</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<!-- should be declared with scope provided --> <!-- should be declared with scope provided -->
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,7 +20,15 @@
package org.sonar.server.charts; package org.sonar.server.charts;


import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.io.Closeables; import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jfree.chart.encoders.KeypointPNGEncoderAdapter; import org.jfree.chart.encoders.KeypointPNGEncoderAdapter;
import org.sonar.api.charts.Chart; import org.sonar.api.charts.Chart;
import org.sonar.api.charts.ChartParameters; import org.sonar.api.charts.ChartParameters;
Expand All @@ -34,17 +42,6 @@
import org.sonar.server.charts.deprecated.SparkLinesChart; import org.sonar.server.charts.deprecated.SparkLinesChart;
import org.sonar.server.platform.Platform; import org.sonar.server.platform.Platform;


import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Map;

public class ChartsServlet extends HttpServlet { public class ChartsServlet extends HttpServlet {


private static final Logger LOG = Loggers.get(ChartsServlet.class); private static final Logger LOG = Loggers.get(ChartsServlet.class);
Expand Down Expand Up @@ -145,15 +142,11 @@ public void deprecatedDoGet(HttpServletRequest request, HttpServletResponse resp
} }


if (chart != null) { if (chart != null) {
OutputStream out = null; try (OutputStream out = response.getOutputStream()) {
try {
out = response.getOutputStream();
response.setContentType("image/png"); response.setContentType("image/png");
chart.exportChartAsPNG(out); chart.exportChartAsPNG(out);
} catch (Exception e) { } catch (Exception e) {
LOG.error("Generating chart " + chart.getClass().getName(), e); LOG.error("Generating chart " + chart.getClass().getName(), e);
} finally {
Closeables.closeQuietly(out);
} }
} }
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.sonar.api.utils.Durations; import org.sonar.api.utils.Durations;
import org.sonar.core.i18n.DefaultI18n; import org.sonar.core.i18n.DefaultI18n;
import org.sonar.core.i18n.RuleI18nManager; import org.sonar.core.i18n.RuleI18nManager;
import org.sonar.core.platform.PluginClassloaderFactory;
import org.sonar.core.platform.PluginLoader; import org.sonar.core.platform.PluginLoader;
import org.sonar.server.db.migrations.DatabaseMigrator; import org.sonar.server.db.migrations.DatabaseMigrator;
import org.sonar.server.db.migrations.PlatformDatabaseMigration; import org.sonar.server.db.migrations.PlatformDatabaseMigration;
Expand All @@ -30,7 +31,7 @@
import org.sonar.server.platform.RailsAppsDeployer; import org.sonar.server.platform.RailsAppsDeployer;
import org.sonar.server.plugins.InstalledPluginReferentialFactory; import org.sonar.server.plugins.InstalledPluginReferentialFactory;
import org.sonar.server.plugins.ServerExtensionInstaller; import org.sonar.server.plugins.ServerExtensionInstaller;
import org.sonar.server.plugins.ServerPluginExploder; import org.sonar.server.plugins.ServerPluginJarExploder;
import org.sonar.server.plugins.ServerPluginRepository; import org.sonar.server.plugins.ServerPluginRepository;
import org.sonar.server.ruby.PlatformRubyBridge; import org.sonar.server.ruby.PlatformRubyBridge;
import org.sonar.server.ui.JRubyI18n; import org.sonar.server.ui.JRubyI18n;
Expand All @@ -51,8 +52,9 @@ protected void configureLevel() {


// plugins // plugins
ServerPluginRepository.class, ServerPluginRepository.class,
ServerPluginExploder.class, ServerPluginJarExploder.class,
PluginLoader.class, PluginLoader.class,
PluginClassloaderFactory.class,
InstalledPluginReferentialFactory.class, InstalledPluginReferentialFactory.class,
ServerExtensionInstaller.class, ServerExtensionInstaller.class,


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ public void installExtensions(ComponentContainer container) {
container.declareExtension(pluginInfo, extension); container.declareExtension(pluginInfo, extension);
} }
} }
} catch (Exception e) { } catch (Throwable e) {
// catch Throwable because we want to catch Error too (IncompatibleClassChangeError, ...)
throw new IllegalStateException(String.format("Fail to load plugin %s [%s]", pluginInfo.getName(), pluginInfo.getKey()), e); throw new IllegalStateException(String.format("Fail to load plugin %s [%s]", pluginInfo.getName(), pluginInfo.getKey()), e);
} }
} }
Expand All @@ -71,7 +72,8 @@ public void installExtensions(ComponentContainer container) {
ExtensionProvider provider = (ExtensionProvider) container.getComponentByKey(extension); ExtensionProvider provider = (ExtensionProvider) container.getComponentByKey(extension);
installProvider(container, pluginInfo, provider); installProvider(container, pluginInfo, provider);
} }
} catch (Exception e) { } catch (Throwable e) {
// catch Throwable because we want to catch Error too (IncompatibleClassChangeError, ...)
throw new IllegalStateException(String.format("Fail to load plugin %s [%s]", pluginInfo.getName(), pluginInfo.getKey()), e); throw new IllegalStateException(String.format("Fail to load plugin %s [%s]", pluginInfo.getName(), pluginInfo.getKey()), e);
} }
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import org.sonar.api.server.ServerSide; import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.ZipUtils; import org.sonar.api.utils.ZipUtils;
import org.sonar.core.platform.ExplodedPlugin; import org.sonar.core.platform.ExplodedPlugin;
import org.sonar.core.platform.PluginExploder; import org.sonar.core.platform.PluginJarExploder;
import org.sonar.core.platform.PluginInfo; import org.sonar.core.platform.PluginInfo;
import org.sonar.server.platform.DefaultServerFileSystem; import org.sonar.server.platform.DefaultServerFileSystem;


Expand All @@ -33,11 +33,11 @@
import static org.apache.commons.io.FileUtils.forceMkdir; import static org.apache.commons.io.FileUtils.forceMkdir;


@ServerSide @ServerSide
public class ServerPluginExploder extends PluginExploder { public class ServerPluginJarExploder extends PluginJarExploder {


private final DefaultServerFileSystem fs; private final DefaultServerFileSystem fs;


public ServerPluginExploder(DefaultServerFileSystem fs) { public ServerPluginJarExploder(DefaultServerFileSystem fs) {
this.fs = fs; this.fs = fs;
} }


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@
import static org.sonar.core.platform.PluginInfo.jarToPluginInfo; import static org.sonar.core.platform.PluginInfo.jarToPluginInfo;


/** /**
* Manages installation and loading of plugins: * Entry point to install and load plugins on server startup. It manages
* <ul> * <ul>
* <li>installation of bundled plugins on first server startup</li> * <li>installation of bundled plugins on first server startup</li>
* <li>installation of new plugins (effective after server startup)</li> * <li>installation of new plugins (effective after server startup)</li>
* <li>un-installation of plugins (effective after server startup)</li> * <li>un-installation of plugins (effective after server startup)</li>
* <li>cancel pending installations/un-installations</li> * <li>cancel pending installations/un-installations</li>
* <li>load plugin bytecode</li> * <li>instantiation of plugin entry-points</li>
* </ul> * </ul>
*/ */
public class ServerPluginRepository implements PluginRepository, Startable { public class ServerPluginRepository implements PluginRepository, Startable {
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;


public class ServerPluginExploderTest { public class ServerPluginJarExploderTest {


@Rule @Rule
public TemporaryFolder temp = new TemporaryFolder(); public TemporaryFolder temp = new TemporaryFolder();


DefaultServerFileSystem fs = mock(DefaultServerFileSystem.class); DefaultServerFileSystem fs = mock(DefaultServerFileSystem.class);
ServerPluginExploder underTest = new ServerPluginExploder(fs); ServerPluginJarExploder underTest = new ServerPluginJarExploder(fs);


@Test @Test
public void copy_all_classloader_files_to_dedicated_directory() throws Exception { public void copy_all_classloader_files_to_dedicated_directory() throws Exception {
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@


import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
Expand All @@ -39,9 +41,6 @@
import org.sonar.server.platform.DefaultServerFileSystem; import org.sonar.server.platform.DefaultServerFileSystem;
import org.sonar.updatecenter.common.Version; import org.sonar.updatecenter.common.Version;


import java.io.File;
import java.io.IOException;

import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
Expand All @@ -58,7 +57,7 @@ public class ServerPluginRepositoryTest {
Server server = mock(Server.class); Server server = mock(Server.class);
ServerUpgradeStatus upgradeStatus = mock(ServerUpgradeStatus.class); ServerUpgradeStatus upgradeStatus = mock(ServerUpgradeStatus.class);
DefaultServerFileSystem fs = mock(DefaultServerFileSystem.class, Mockito.RETURNS_DEEP_STUBS); DefaultServerFileSystem fs = mock(DefaultServerFileSystem.class, Mockito.RETURNS_DEEP_STUBS);
PluginLoader pluginLoader = new PluginLoader(new ServerPluginExploder(fs)); PluginLoader pluginLoader = mock(PluginLoader.class);
ServerPluginRepository underTest = new ServerPluginRepository(server, upgradeStatus, fs, pluginLoader); ServerPluginRepository underTest = new ServerPluginRepository(server, upgradeStatus, fs, pluginLoader);


@Before @Before
Expand Down Expand Up @@ -91,9 +90,6 @@ public void first_startup_installs_bundled_plugins() throws Exception {


// both plugins are installed // both plugins are installed
assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("core", "testbase"); assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("core", "testbase");
assertThat(underTest.getPluginInstance("core").getClass().getName()).isEqualTo("CorePlugin");
assertThat(underTest.getPluginInstance("testbase").getClass().getName()).isEqualTo("BasePlugin");
assertThat(underTest.hasPlugin("testbase")).isTrue();
} }


@Test @Test
Expand All @@ -115,8 +111,6 @@ public void standard_startup_loads_core_and_installed_plugins() throws Exception


// both plugins are installed // both plugins are installed
assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("core", "testbase"); assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("core", "testbase");
assertThat(underTest.getPluginInstance("core").getClass().getName()).isEqualTo("CorePlugin");
assertThat(underTest.getPluginInstance("testbase").getClass().getName()).isEqualTo("BasePlugin");
} }


/** /**
Expand Down Expand Up @@ -160,7 +154,6 @@ public void install_downloaded_plugins_on_startup() throws Exception {
assertThat(downloadedJar).doesNotExist(); assertThat(downloadedJar).doesNotExist();
assertThat(new File(fs.getInstalledPluginsDir(), downloadedJar.getName())).isFile().exists(); assertThat(new File(fs.getInstalledPluginsDir(), downloadedJar.getName())).isFile().exists();
assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase"); assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase");
assertThat(underTest.getPluginInstance("testbase").getClass().getName()).isEqualTo("BasePlugin");
} }


@Test @Test
Expand Down
4 changes: 4 additions & 0 deletions sonar-batch/pom.xml
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
<groupId>org.codehaus.sonar</groupId> <groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-persistit</artifactId> <artifactId>sonar-persistit</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>


<dependency> <dependency>
<groupId>org.codehaus.sonar</groupId> <groupId>org.codehaus.sonar</groupId>
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import org.sonar.api.batch.BatchSide; import org.sonar.api.batch.BatchSide;
import org.sonar.api.utils.ZipUtils; import org.sonar.api.utils.ZipUtils;
import org.sonar.core.platform.ExplodedPlugin; import org.sonar.core.platform.ExplodedPlugin;
import org.sonar.core.platform.PluginExploder; import org.sonar.core.platform.PluginJarExploder;
import org.sonar.core.platform.PluginInfo; import org.sonar.core.platform.PluginInfo;
import org.sonar.home.cache.FileCache; import org.sonar.home.cache.FileCache;


Expand All @@ -32,11 +32,11 @@
import java.io.IOException; import java.io.IOException;


@BatchSide @BatchSide
public class BatchPluginExploder extends PluginExploder { public class BatchPluginJarExploder extends PluginJarExploder {


private final FileCache fileCache; private final FileCache fileCache;


public BatchPluginExploder(FileCache fileCache) { public BatchPluginJarExploder(FileCache fileCache) {
this.fileCache = fileCache; this.fileCache = fileCache;
} }


Expand Down

This file was deleted.

Loading

0 comments on commit 0956511

Please sign in to comment.