The core plugin was highly coupled with core, so it did not respect classloader isolation
as other plugins.
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.codehaus.sonar</groupId>
- <artifactId>sonar</artifactId>
- <version>5.2-SNAPSHOT</version>
- <relativePath>../..</relativePath>
- </parent>
- <groupId>org.codehaus.sonar.plugins</groupId>
- <artifactId>sonar-core-plugin</artifactId>
- <packaging>sonar-plugin</packaging>
- <name>SonarQube :: Plugins :: Core</name>
-
- <dependencies>
- <dependency>
- <groupId>org.codehaus.sonar</groupId>
- <artifactId>sonar-plugin-api</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>jsr305</artifactId>
- <scope>provided</scope>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.codehaus.sonar</groupId>
- <artifactId>sonar-packaging-maven-plugin</artifactId>
- <configuration>
- <pluginKey>core</pluginKey>
- <pluginName>Core</pluginName>
- <pluginClass>org.sonar.plugins.core.CorePlugin</pluginClass>
- <pluginDescription>
- <![CDATA[Provides all common components required to cover all languages.]]></pluginDescription>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
+++ /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.plugins.core;
-
-import java.util.Collections;
-import java.util.List;
-import org.sonar.api.SonarPlugin;
-
-public final class CorePlugin extends SonarPlugin {
-
- @Override
- public List getExtensions() {
- return Collections.emptyList();
- }
-
-}
+++ /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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.plugins.core;
-
-import javax.annotation.ParametersAreNonnullByDefault;
<module>sonar-plugin-api</module>
<module>server</module>
<module>sonar-testing-harness</module>
- <module>plugins/sonar-core-plugin</module>
<module>plugins/sonar-l10n-en-plugin</module>
<module>plugins/sonar-email-notifications-plugin</module>
<module>plugins/sonar-xoo-plugin</module>
</dependency>
<!-- core plugins -->
- <dependency>
- <groupId>org.codehaus.sonar.plugins</groupId>
- <artifactId>sonar-core-plugin</artifactId>
- <version>${project.version}</version>
- <type>sonar-plugin</type>
- <scope>provided</scope>
- </dependency>
<dependency>
<groupId>org.codehaus.sonar.plugins</groupId>
<artifactId>sonar-l10n-en-plugin</artifactId>
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.Nonnull;
import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.BatchSide;
import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.BatchSide;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import javax.annotation.Nonnull;
-
-import java.text.MessageFormat;
-import java.util.List;
-import java.util.Set;
-
import static com.google.common.collect.Sets.newHashSet;
/**
* Filters the plugins to be enabled during analysis
*/
@BatchSide
-public class BatchPluginPredicate implements Predicate<String>{
+public class BatchPluginPredicate implements Predicate<String> {
private static final Logger LOG = Loggers.get(BatchPluginPredicate.class);
- private static final String CORE_PLUGIN_KEY = "core";
private static final String BUILDBREAKER_PLUGIN_KEY = "buildbreaker";
private static final String PROPERTY_IS_DEPRECATED_MSG = "Property {0} is deprecated. Please use {1} instead.";
private static final Joiner COMMA_JOINER = Joiner.on(", ");
@Override
public boolean apply(@Nonnull String pluginKey) {
- if (CORE_PLUGIN_KEY.equals(pluginKey)) {
- return !mode.isMediumTest();
- }
-
if (BUILDBREAKER_PLUGIN_KEY.equals(pluginKey) && mode.isPreview()) {
LOG.info("Build Breaker plugin is no more supported in preview/incremental mode");
return false;
assertThat(predicate.apply("pmd")).isTrue();
}
- @Test
- public void accept_core_plugin_even_if_not_in_inclusions() {
- when(mode.isPreview()).thenReturn(true);
- settings.setProperty(CoreProperties.PREVIEW_INCLUDE_PLUGINS, "checkstyle,pmd,findbugs");
- BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode);
- assertThat(predicate.apply("core")).isTrue();
- }
-
- @Test
- public void accept_core_plugin_even_if_declared_in_exclusions() {
- when(mode.isPreview()).thenReturn(true);
- settings.setProperty(CoreProperties.PREVIEW_EXCLUDE_PLUGINS, "core,findbugs");
- BatchPluginPredicate predicate = new BatchPluginPredicate(settings, mode);
- assertThat(predicate.apply("core")).isTrue();
- }
-
@Test
public void verify_both_inclusions_and_exclusions() {
when(mode.isPreview()).thenReturn(true);
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
-import org.apache.commons.io.IOUtils;
-import org.picocontainer.Startable;
-import org.sonar.api.batch.BatchSide;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.utils.SonarException;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.core.platform.PluginInfo;
-import org.sonar.core.platform.PluginRepository;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.io.IOUtils;
+import org.picocontainer.Startable;
+import org.sonar.api.batch.BatchSide;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.server.ServerSide;
+import org.sonar.api.utils.SonarException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.core.platform.PluginInfo;
+import org.sonar.core.platform.PluginRepository;
@BatchSide
@ServerSide
void doStart(ClassLoader classloader) {
this.classloader = classloader;
this.propertyToBundles = new HashMap<>();
+
+ // org.sonar.l10n.core bundle is provided by sonar-core module
+ initPlugin("core");
+
Collection<PluginInfo> infos = pluginRepository.getPluginInfos();
- if (infos.isEmpty()) {
- addPlugin("core");
- } else {
- for (PluginInfo plugin : infos) {
- addPlugin(plugin.getKey());
- }
+ for (PluginInfo plugin : infos) {
+ initPlugin(plugin.getKey());
}
LOG.debug("Loaded {} properties from l10n bundles", propertyToBundles.size());
}
- private void addPlugin(String pluginKey) {
+ private void initPlugin(String pluginKey) {
try {
String bundleKey = BUNDLE_PACKAGE + pluginKey;
ResourceBundle bundle = ResourceBundle.getBundle(bundleKey, Locale.ENGLISH, this.classloader, control);
}
return MessageFormat.format(message.replaceAll("'", "''"), parameters);
}
-
- ClassLoader getBundleClassLoader() {
- return classloader;
- }
}
Plugin plugin = pluginRepository.getPluginInstance(info.getKey());
list.add(plugin.getClass().getClassLoader());
}
+ list.add(I18nClassloader.class.getClassLoader());
return list;
}
}
*/
package org.sonar.core.i18n;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginRepository;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-import java.util.TimeZone;
-
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@Before
public void before() {
PluginRepository pluginRepository = mock(PluginRepository.class);
- List<PluginInfo> plugins = Arrays.asList(newPlugin("core"), newPlugin("sqale"), newPlugin("frpack"), newPlugin("checkstyle"), newPlugin("other"));
+ List<PluginInfo> plugins = Arrays.asList(newPlugin("sqale"), newPlugin("frpack"), newPlugin("checkstyle"), newPlugin("other"));
when(pluginRepository.getPluginInfos()).thenReturn(plugins);
manager = new DefaultI18n(pluginRepository, system2);
}
@Test
- public void load_core_bundle_when_no_plugin() {
- DefaultI18n manager = new DefaultI18n(mock(PluginRepository.class), system2);
- manager.doStart(getClass().getClassLoader());
-
- assertThat(manager.getPropertyKeys().contains("any")).isTrue();
- assertThat(manager.getPropertyKeys().contains("assignee")).isTrue();
+ public void load_core_bundle() {
+ assertThat(manager.message(Locale.ENGLISH, "any", null)).isEqualTo("Any");
}
@Test
assertThat(manager.formatInteger(Locale.ENGLISH, 100000)).isEqualTo("100,000");
}
- static URLClassLoader newCheckstyleClassloader() {
- return newClassLoader("/org/sonar/core/i18n/I18nClassloaderTest/");
- }
-
- /**
- * Example of plugin that embeds its own translations (English + French).
- */
- static URLClassLoader newSqaleClassloader() {
- return newClassLoader("/org/sonar/core/i18n/sqalePlugin/");
- }
-
- /**
- * "Language Pack" contains various translations for different plugins.
- */
- static URLClassLoader newFrenchPackClassloader() {
- return newClassLoader("/org/sonar/core/i18n/frenchPack/");
- }
-
- private static URLClassLoader newClassLoader(String... resourcePaths) {
- URL[] urls = new URL[resourcePaths.length];
- for (int index = 0; index < resourcePaths.length; index++) {
- urls[index] = DefaultI18nTest.class.getResource(resourcePaths[index]);
- }
- return new URLClassLoader(urls);
- }
-
private PluginInfo newPlugin(String key) {
PluginInfo plugin = mock(PluginInfo.class);
when(plugin.getKey()).thenReturn(key);