import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchExtension;
import org.sonar.api.platform.PluginRepository;
import org.sonar.api.utils.SonarException;
+import javax.annotation.Nullable;
+
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
-import java.util.Collections;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
public class I18nManager implements I18n, ServerExtension, BatchExtension {
private static final Logger LOG = LoggerFactory.getLogger(I18nManager.class);
- public static final String ENGLISH_PACK_PLUGIN_KEY = "l10nen";
public static final String BUNDLE_PACKAGE = "org.sonar.l10n.";
private PluginRepository pluginRepository;
- private Map<String, ClassLoader> bundleToClassloaders;
+ private I18nClassloader i18nClassloader;
private Map<String, String> propertyToBundles;
- private ClassLoader languagePackClassLoader;
private Map<String, Map<Locale, String>> fileContentCache = Maps.newHashMap();
public I18nManager(PluginRepository pluginRepository) {
this.pluginRepository = pluginRepository;
}
- @VisibleForTesting
- I18nManager(Map<String, ClassLoader> bundleToClassloaders, ClassLoader languagePackClassLoader) {
- this.bundleToClassloaders = bundleToClassloaders;
- this.languagePackClassLoader = languagePackClassLoader;
- }
-
public void start() {
- initClassloaders();
- initProperties();
+ doStart(new I18nClassloader(pluginRepository));
}
- private void initClassloaders() {
- if (bundleToClassloaders == null) {
- languagePackClassLoader = pluginRepository.getPlugin(ENGLISH_PACK_PLUGIN_KEY).getClass().getClassLoader();
- bundleToClassloaders = Maps.newHashMap();
- for (PluginMetadata metadata : pluginRepository.getMetadata()) {
- if (!ENGLISH_PACK_PLUGIN_KEY.equals(metadata.getKey())
- && !ENGLISH_PACK_PLUGIN_KEY.equals(metadata.getBasePlugin())) {
- // This is a "simple" plugin, not a Language Pack
- ClassLoader classLoader = pluginRepository.getPlugin(metadata.getKey()).getClass().getClassLoader();
- bundleToClassloaders.put(BUNDLE_PACKAGE + metadata.getKey(), classLoader);
- }
- }
- }
- bundleToClassloaders = Collections.unmodifiableMap(bundleToClassloaders);
- }
-
- private void initProperties() {
+ @VisibleForTesting
+ void doStart(I18nClassloader classloader) {
+ this.i18nClassloader = classloader;
propertyToBundles = Maps.newHashMap();
- for (Map.Entry<String, ClassLoader> entry : bundleToClassloaders.entrySet()) {
+ for (PluginMetadata plugin : pluginRepository.getMetadata()) {
try {
- String bundleKey = entry.getKey();
- ResourceBundle bundle = ResourceBundle.getBundle(bundleKey, Locale.ENGLISH, entry.getValue());
+ String bundleKey = BUNDLE_PACKAGE + plugin.getKey();
+ ResourceBundle bundle = ResourceBundle.getBundle(bundleKey, Locale.ENGLISH, i18nClassloader);
Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
// ignore
}
}
- propertyToBundles = Collections.unmodifiableMap(propertyToBundles);
- LOG.debug(String.format("Loaded %d properties from English bundles", propertyToBundles.size()));
+ LOG.debug(String.format("Loaded %d properties from l10n bundles", propertyToBundles.size()));
}
public String message(Locale locale, String key, String defaultValue, Object... parameters) {
String bundleKey = propertyToBundles.get(key);
- ResourceBundle resourceBundle = null;
+ String value = null;
if (bundleKey != null) {
try {
- // First, we check if the bundle exists in the language pack classloader
- resourceBundle = ResourceBundle.getBundle(bundleKey, locale, languagePackClassLoader);
- String message = resourceBundle.getString(key);
- return formatMessage(message, parameters);
+ ResourceBundle resourceBundle = ResourceBundle.getBundle(bundleKey, locale, i18nClassloader);
+ value = resourceBundle.getString(key);
} catch (MissingResourceException e1) {
- // well, maybe the plugin has specified its own bundles, let's see
- resourceBundle = getBundleFromCorrespondingPluginClassloader(bundleKey, locale);
+ // ignore
}
}
- return message(resourceBundle, key, defaultValue, parameters);
+ if (value == null) {
+ value = defaultValue;
+ }
+ return formatMessage(value, parameters);
}
/**
return fileCache.get(locale);
}
- ClassLoader classloader = getClassLoaderForProperty(relatedProperty, locale);
String result = null;
- if (classloader != null) {
- String bundleBase = propertyToBundles.get(relatedProperty);
- String filePath = bundleBase.replace('.', '/');
- if (!"en".equals(locale.getLanguage())) {
- filePath += "_" + locale.getLanguage();
- }
- filePath += "/" + filename;
- InputStream input = classloader.getResourceAsStream(filePath);
- if (input != null) {
- result = readInputStream(filePath, input);
- }
+ String bundleBase = propertyToBundles.get(relatedProperty);
+ String filePath = bundleBase.replace('.', '/');
+ if (!"en".equals(locale.getLanguage())) {
+ filePath += "_" + locale.getLanguage();
+ }
+ filePath += "/" + filename;
+ InputStream input = i18nClassloader.getResourceAsStream(filePath);
+ if (input != null) {
+ result = readInputStream(filePath, input);
+ }
- if (keepInCache) {
- if (fileCache == null) {
- fileCache = Maps.newHashMap();
- fileContentCache.put(filename, fileCache);
- }
- // put null value for negative caching.
- fileCache.put(locale, result);
+ if (keepInCache) {
+ if (fileCache == null) {
+ fileCache = Maps.newHashMap();
+ fileContentCache.put(filename, fileCache);
}
+ // put null value for negative caching.
+ fileCache.put(locale, result);
}
return result;
}
return result;
}
+ @VisibleForTesting
Set<String> getPropertyKeys() {
return propertyToBundles.keySet();
}
- ResourceBundle getBundleFromCorrespondingPluginClassloader(String bundleKey, Locale locale) {
- ClassLoader classloader = bundleToClassloaders.get(bundleKey);
- if (classloader != null) {
- try {
- return ResourceBundle.getBundle(bundleKey, locale, classloader);
- } catch (MissingResourceException e2) {
- // Well, here, there's nothing much we can do...
- }
- }
- return null;
- }
-
- ClassLoader getClassLoaderForProperty(String propertyKey, Locale locale) {
- String bundleKey = propertyToBundles.get(propertyKey);
- if (bundleKey == null) {
- return null;
- }
-
- try {
- // First, we check if the bundle exists in the language pack classloader
- ResourceBundle.getBundle(bundleKey, locale, languagePackClassLoader);
- return languagePackClassLoader;
- } catch (MissingResourceException e) {
- // the plugin has specified its own bundles
- return bundleToClassloaders.get(bundleKey);
- }
- }
-
- String message(ResourceBundle resourceBundle, String key, String defaultValue, Object... parameters) {
- String value = null;
- if (resourceBundle != null) {
- try {
- value = resourceBundle.getString(key);
- } catch (MissingResourceException e) {
- // ignore
- }
- }
- if (value == null) {
- value = defaultValue;
- }
- return formatMessage(value, parameters);
- }
-
- private String formatMessage(String message, Object... parameters) {
+ private String formatMessage(@Nullable String message, Object... parameters) {
if (message == null || parameters.length == 0) {
return message;
}
return MessageFormat.format(message.replaceAll("'", "''"), parameters);
}
- String extractBundleFromKey(String key) {
- String bundleKey = BUNDLE_PACKAGE + StringUtils.substringBefore(key, ".");
- if (bundleToClassloaders.containsKey(bundleKey)) {
- return bundleKey;
- }
- return BUNDLE_PACKAGE + "core";
- }
- ClassLoader getLanguagePackClassLoader() {
- return languagePackClassLoader;
+ ClassLoader getBundleClassLoader() {
+ return i18nClassloader;
}
Map<String, Map<Locale, String>> getFileContentCache() {
*/
package org.sonar.core.i18n;
-import com.google.common.collect.Maps;
-import org.hamcrest.core.Is;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.sonar.api.platform.PluginMetadata;
+import org.sonar.api.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.Map;
import static org.fest.assertions.Assertions.assertThat;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertThat;
-import static org.sonar.core.i18n.I18nManager.BUNDLE_PACKAGE;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class I18nManagerTest {
private static Locale defaultLocale;
private I18nManager manager;
- private ClassLoader coreClassLoader;
- private ClassLoader sqaleClassLoader;
- private ClassLoader forgeClassLoader;
/**
* See http://jira.codehaus.org/browse/SONAR-2927
@Before
public void init() {
- Map<String, ClassLoader> bundleToClassLoaders = Maps.newHashMap();
- // following represents the English language pack + a core plugin : they use the same classloader
- coreClassLoader = newCoreClassLoader();
- bundleToClassLoaders.put(BUNDLE_PACKAGE + "core", coreClassLoader);
- bundleToClassLoaders.put(BUNDLE_PACKAGE + "checkstyle", coreClassLoader);
- // following represents a commercial plugin that must embed all its bundles, whatever the language
- sqaleClassLoader = newSqaleClassLoader();
- bundleToClassLoaders.put(BUNDLE_PACKAGE + "sqale", sqaleClassLoader);
- // following represents a forge plugin that embeds only the english bundle, and lets the language
- // packs embed all the bundles for the other languages
- forgeClassLoader = newForgeClassLoader();
- bundleToClassLoaders.put(BUNDLE_PACKAGE + "forge", forgeClassLoader);
-
- manager = new I18nManager(bundleToClassLoaders, coreClassLoader);
- manager.start();
+ PluginRepository pluginRepository = mock(PluginRepository.class);
+ List<PluginMetadata> plugins = Arrays.asList(newPlugin("sqale"), newPlugin("frpack"), newPlugin("core"), newPlugin("checkstyle"), newPlugin("other"));
+ when(pluginRepository.getMetadata()).thenReturn(plugins);
+
+ I18nClassloader i18nClassloader = new I18nClassloader(new ClassLoader[]{
+ newCoreClassloader(), newFrenchPackClassloader(), newSqaleClassloader(), newCheckstyleClassloader()
+ });
+ manager = new I18nManager(pluginRepository);
+ manager.doStart(i18nClassloader);
}
@Test
- public void shouldExtractPluginFromKey() {
- Map<String, ClassLoader> bundleToClassLoaders = Maps.newHashMap();
- bundleToClassLoaders.put(BUNDLE_PACKAGE + "core", getClass().getClassLoader());
- bundleToClassLoaders.put(BUNDLE_PACKAGE + "checkstyle", getClass().getClassLoader());
- bundleToClassLoaders.put(BUNDLE_PACKAGE + "sqale", getClass().getClassLoader());
- I18nManager i18n = new I18nManager(bundleToClassLoaders, coreClassLoader);
- i18n.start();
+ public void should_introspect_all_available_properties() {
+ assertThat(manager.getPropertyKeys().contains("by")).isTrue();
+ assertThat(manager.getPropertyKeys().contains("only.in.english")).isTrue();
+ assertThat(manager.getPropertyKeys().contains("sqale.page")).isTrue();
+ assertThat(manager.getPropertyKeys().contains("unknown")).isFalse();
+ }
- assertThat(i18n.extractBundleFromKey("by"), Is.is(BUNDLE_PACKAGE + "core"));
- assertThat(i18n.extractBundleFromKey("violations_drilldown.page"), Is.is(BUNDLE_PACKAGE + "core"));
- assertThat(i18n.extractBundleFromKey("checkstyle.rule1.name"), Is.is(BUNDLE_PACKAGE + "checkstyle"));
- assertThat(i18n.extractBundleFromKey("sqale.console.page"), Is.is(BUNDLE_PACKAGE + "sqale"));
+ @Test
+ public void should_get_english_labels() {
+ assertThat(manager.message(Locale.ENGLISH, "by", null)).isEqualTo("By");
+ assertThat(manager.message(Locale.ENGLISH, "sqale.page", null)).isEqualTo("Sqale page title");
+ assertThat(manager.message(Locale.ENGLISH, "checkstyle.rule1.name", null)).isEqualTo("Rule one");
}
@Test
- public void shouldFindKeysInEnglishLanguagePack() {
- assertThat(manager.message(Locale.ENGLISH, "checkstyle.rule1.name", null), Is.is("Rule one"));
- assertThat(manager.message(Locale.ENGLISH, "by", null), Is.is("By"));
- assertThat(manager.message(Locale.ENGLISH, "sqale.page", null), Is.is("Sqale page title"));
+ public void should_get_labels_from_french_pack() {
+ assertThat(manager.message(Locale.FRENCH, "checkstyle.rule1.name", null)).isEqualTo("Rule un");
+ assertThat(manager.message(Locale.FRENCH, "by", null)).isEqualTo("Par");
- assertThat(manager.message(Locale.FRENCH, "checkstyle.rule1.name", null), Is.is("Rule un"));
- assertThat(manager.message(Locale.FRENCH, "by", null), Is.is("Par"));
- assertThat(manager.message(Locale.FRENCH, "sqale.page", null), Is.is("Titre de la page Sqale"));
+ // language pack
+ assertThat(manager.message(Locale.FRENCH, "sqale.page", null)).isEqualTo("Titre de la page Sqale");
}
@Test
- public void shouldUseDefaultLocale() {
- assertThat(manager.message(Locale.CHINA, "checkstyle.rule1.name", null), Is.is("Rule one"));
- assertThat(manager.message(Locale.CHINA, "by", null), Is.is("By"));
- assertThat(manager.message(Locale.CHINA, "sqale.page", null), Is.is("Sqale page title"));
+ public void should_get_french_label_if_swiss_country() {
+ Locale swiss = new Locale("fr", "CH");
+ assertThat(manager.message(swiss, "checkstyle.rule1.name", null)).isEqualTo("Rule un");
+ assertThat(manager.message(swiss, "by", null)).isEqualTo("Par");
+
+ // language pack
+ assertThat(manager.message(swiss, "sqale.page", null)).isEqualTo("Titre de la page Sqale");
}
@Test
- public void shouldUseLanguagePack() {
- assertThat(manager.message(Locale.FRENCH, "checkstyle.rule1.name", null), Is.is("Rule un"));
- assertThat(manager.message(Locale.FRENCH, "by", null), Is.is("Par"));
- assertThat(manager.message(Locale.FRENCH, "sqale.page", null), Is.is("Titre de la page Sqale"));
+ public void should_fallback_to_default_locale() {
+ assertThat(manager.message(Locale.CHINA, "checkstyle.rule1.name", null)).isEqualTo("Rule one");
+ assertThat(manager.message(Locale.CHINA, "by", null)).isEqualTo("By");
+ assertThat(manager.message(Locale.CHINA, "sqale.page", null)).isEqualTo("Sqale page title");
}
+
@Test
- public void shouldReturnDefaultValueIfMissingKey() {
- assertThat(manager.message(Locale.ENGLISH, "foo.unknown", "default"), Is.is("default"));
- assertThat(manager.message(Locale.FRENCH, "foo.unknown", "default"), Is.is("default"));
+ public void should_return_default_value_if_missing_key() {
+ assertThat(manager.message(Locale.ENGLISH, "unknown", "default")).isEqualTo("default");
+ assertThat(manager.message(Locale.FRENCH, "unknown", "default")).isEqualTo("default");
}
@Test
- public void shouldAcceptEmptyLabels() {
- assertThat(manager.message(Locale.ENGLISH, "empty", "default"), Is.is(""));
- assertThat(manager.message(Locale.FRENCH, "empty", "default"), Is.is(""));
+ public void should_accept_empty_labels() {
+ assertThat(manager.message(Locale.ENGLISH, "empty", "default")).isEqualTo("");
+ assertThat(manager.message(Locale.FRENCH, "empty", "default")).isEqualTo("");
}
@Test
public void shouldFormatMessageWithParameters() {
- assertThat(manager.message(Locale.ENGLISH, "with.parameters", null, "one", "two"), Is.is("First is one and second is two"));
+ assertThat(manager.message(Locale.ENGLISH, "with.parameters", null, "one", "two")).isEqualTo("First is one and second is two");
}
@Test
public void shouldUseDefaultLocaleIfMissingValueInLocalizedBundle() {
- assertThat(manager.message(Locale.FRENCH, "only.in.english", null), Is.is("Missing in French bundle"));
- assertThat(manager.message(Locale.CHINA, "only.in.english", null), Is.is("Missing in French bundle"));
+ assertThat(manager.message(Locale.FRENCH, "only.in.english", null)).isEqualTo("Missing in French bundle");
+ assertThat(manager.message(Locale.CHINA, "only.in.english", null)).isEqualTo("Missing in French bundle");
}
@Test
- public void shouldGetClassLoaderByProperty() {
- assertThat(manager.getClassLoaderForProperty("foo.unknown", Locale.ENGLISH), nullValue());
- assertThat(manager.getClassLoaderForProperty("by", Locale.ENGLISH), Is.is(coreClassLoader));
- // The following plugin defines its own bundles, whatever the language
- assertThat(manager.getClassLoaderForProperty("sqale.page", Locale.ENGLISH), Is.is(sqaleClassLoader));
- assertThat(manager.getClassLoaderForProperty("sqale.page", Locale.FRENCH), Is.is(sqaleClassLoader));
- // The following plugin defines only the English bundle, and lets the language packs handle the translations
- assertThat(manager.getClassLoaderForProperty("forge_plugin.page", Locale.ENGLISH), Is.is(forgeClassLoader));
- assertThat(manager.getClassLoaderForProperty("forge_plugin.page", Locale.FRENCH), Is.is(coreClassLoader));
+ public void should_locate_english_file() {
+ String html = manager.messageFromFile(Locale.ENGLISH, "ArchitectureRule.html", "checkstyle.rule1.name", false);
+ assertThat(html).isEqualTo("This is the architecture rule");
}
@Test
- public void shouldFindEnglishFile() {
- String html = manager.messageFromFile(Locale.ENGLISH, "ArchitectureRule.html", "checkstyle.rule1.name" /*
- * any property in the same
- * bundle
- */, false);
- assertThat(html, Is.is("This is the architecture rule"));
+ public void should_return_null_if_file_not_found() {
+ String html = manager.messageFromFile(Locale.ENGLISH, "UnknownRule.html", "checkstyle.rule1.name", false);
+ assertThat(html).isNull();
}
@Test
- public void shouldNotFindFile() {
- String html = manager.messageFromFile(Locale.ENGLISH, "UnknownRule.html", "checkstyle.rule1.name" /* any property in the same bundle */, false);
- assertThat(html, nullValue());
+ public void should_locate_french_file() {
+ String html = manager.messageFromFile(Locale.FRENCH, "ArchitectureRule.html", "checkstyle.rule1.name", false);
+ assertThat(html).isEqualTo("Règle d'architecture");
}
@Test
- public void shouldFindFrenchFile() {
- String html = manager.messageFromFile(Locale.FRENCH, "ArchitectureRule.html", "checkstyle.rule1.name" /* any property in the same bundle */, false);
- assertThat(html, Is.is("Règle d'architecture"));
+ public void should_locate_file_with_missing_locale() {
+ String html = manager.messageFromFile(Locale.CHINA, "ArchitectureRule.html", "checkstyle.rule1.name", false);
+ assertThat(html).isNull();
}
@Test
- public void shouldNotFindMissingLocale() {
- String html = manager.messageFromFile(Locale.CHINA, "ArchitectureRule.html", "checkstyle.rule1.name" /* any property in the same bundle */, false);
- assertThat(html, nullValue());
- }
-
- @Test
- public void shouldNotKeepInCache() {
- assertThat(manager.getFileContentCache().size(), Is.is(0));
+ public void should_not_keep_in_cache() {
+ assertThat(manager.getFileContentCache()).isEmpty();
boolean keepInCache = false;
- String html = manager.messageFromFile(Locale.ENGLISH, "ArchitectureRule.html", "checkstyle.rule1.name" /*
- * any property in the same
- * bundle
- */, keepInCache);
+ String html = manager.messageFromFile(Locale.ENGLISH, "ArchitectureRule.html", "checkstyle.rule1.name", keepInCache);
- assertThat(html, not(nullValue()));
- assertThat(manager.getFileContentCache().size(), Is.is(0));
+ assertThat(html).isNotNull();
+ assertThat(manager.getFileContentCache()).isEmpty();
}
@Test
- public void shouldKeepInCache() {
- assertThat(manager.getFileContentCache().size(), Is.is(0));
+ public void should_keep_in_cache() {
+ assertThat(manager.getFileContentCache()).isEmpty();
boolean keepInCache = true;
- String html = manager.messageFromFile(Locale.ENGLISH, "ArchitectureRule.html", "checkstyle.rule1.name" /*
- * any property in the same
- * bundle
- */, keepInCache);
+ String html = manager.messageFromFile(Locale.ENGLISH, "ArchitectureRule.html", "checkstyle.rule1.name", keepInCache);
+ assertThat(html).isEqualTo("This is the architecture rule");
- assertThat(html, not(nullValue()));
- Map<String, Map<Locale, String>> cache = manager.getFileContentCache();
- assertThat(cache.size(), Is.is(1));
- assertThat(cache.get("ArchitectureRule.html").get(Locale.ENGLISH), Is.is("This is the architecture rule"));
- }
+ html = manager.messageFromFile(Locale.ENGLISH, "ArchitectureRule.html", "checkstyle.rule1.name", keepInCache);
+ assertThat(html).isEqualTo("This is the architecture rule");
+ assertThat(manager.getFileContentCache()).hasSize(1);
- // see SONAR-3596
- @Test
- public void shouldLookInCoreClassloaderForPluginsThatDontEmbedAllLanguages() {
- assertThat(manager.message(Locale.ENGLISH, "forge_plugin.page", null)).isEqualTo("This is my plugin");
- assertThat(manager.message(Locale.FRENCH, "forge_plugin.page", null)).isEqualTo("C'est mon plugin");
+ html = manager.messageFromFile(Locale.FRENCH, "ArchitectureRule.html", "checkstyle.rule1.name", keepInCache);
+ assertThat(html).isEqualTo("Règle d'architecture");
+ assertThat(manager.getFileContentCache()).hasSize(1);
}
- // see SONAR-3783 => test that there will be no future regression on fallback for keys spread accross several classloaders
- @Test
- public void shouldFallbackOnOriginalPluginIfTranslationNotPresentInLanguagePack() {
- // the "forge_plugin.page" has been translated in French
- assertThat(manager.message(Locale.FRENCH, "forge_plugin.page", null)).isEqualTo("C'est mon plugin");
- // but not the "forge_plugin.key_not_translated" key
- assertThat(manager.message(Locale.FRENCH, "forge_plugin.key_not_translated", null)).isEqualTo("Key Not Translated");
+ static URLClassLoader newCoreClassloader() {
+ return newClassLoader("/org/sonar/core/i18n/corePlugin/");
}
- private URLClassLoader newForgeClassLoader() {
- return newClassLoader("/org/sonar/core/i18n/forgePlugin/");
+ static URLClassLoader newCheckstyleClassloader() {
+ return newClassLoader("/org/sonar/core/i18n/checkstylePlugin/");
}
- private URLClassLoader newSqaleClassLoader() {
+ /**
+ * Example of plugin that embeds its own translations (English + French).
+ */
+ static URLClassLoader newSqaleClassloader() {
return newClassLoader("/org/sonar/core/i18n/sqalePlugin/");
}
- private URLClassLoader newCoreClassLoader() {
- return newClassLoader("/org/sonar/core/i18n/englishPack/", "/org/sonar/core/i18n/frenchPack/");
+ /**
+ * "Language Pack" contains various translations for different plugins.
+ */
+ static URLClassLoader newFrenchPackClassloader() {
+ return newClassLoader("/org/sonar/core/i18n/frenchPack/");
}
- private URLClassLoader newClassLoader(String... resourcePaths) {
+ private static URLClassLoader newClassLoader(String... resourcePaths) {
URL[] urls = new URL[resourcePaths.length];
for (int index = 0; index < resourcePaths.length; index++) {
- urls[index] = getClass().getResource(resourcePaths[index]);
+ urls[index] = I18nManagerTest.class.getResource(resourcePaths[index]);
}
return new URLClassLoader(urls);
}
+
+ private PluginMetadata newPlugin(String key) {
+ PluginMetadata plugin = mock(PluginMetadata.class);
+ when(plugin.getKey()).thenReturn(key);
+ return plugin;
+ }
}