diff --git a/pom.xml b/pom.xml index f88eb21..f13d116 100644 --- a/pom.xml +++ b/pom.xml @@ -32,30 +32,32 @@ + 1.7.36 2020-01-20T18:52:37Z - org.codehaus.plexus - plexus-container-default - 2.1.1 + javax.inject + javax.inject + 1 - org.codehaus.plexus - plexus-component-annotations - 2.2.0 - provided + org.slf4j + slf4j-api + ${slf4jVersion} - org.codehaus.plexus - plexus-utils - 4.0.0 + org.slf4j + slf4j-simple + ${slf4jVersion} + test org.codehaus.plexus - plexus-xml - 3.0.0 + plexus-testing + 1.3.0 + test @@ -79,6 +81,10 @@ + + org.eclipse.sisu + sisu-maven-plugin + diff --git a/src/main/java/org/codehaus/plexus/i18n/DefaultI18N.java b/src/main/java/org/codehaus/plexus/i18n/DefaultI18N.java index fc74e8f..62b8b03 100644 --- a/src/main/java/org/codehaus/plexus/i18n/DefaultI18N.java +++ b/src/main/java/org/codehaus/plexus/i18n/DefaultI18N.java @@ -16,7 +16,8 @@ * limitations under the License. */ -import java.lang.reflect.Field; +import javax.inject.Named; + import java.text.MessageFormat; import java.util.HashMap; import java.util.Locale; @@ -24,43 +25,44 @@ import java.util.MissingResourceException; import java.util.ResourceBundle; -import org.codehaus.plexus.component.annotations.Component; -import org.codehaus.plexus.logging.AbstractLogEnabled; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.codehaus.plexus.util.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * */ -@Component(role = I18N.class) -public class DefaultI18N extends AbstractLogEnabled implements I18N, Initializable { +@Named +public class DefaultI18N implements I18N { + + private final Logger log = LoggerFactory.getLogger(DefaultI18N.class); private static final Object[] NO_ARGS = new Object[0]; - private HashMap bundles; + private Map> bundles; private String[] bundleNames; private String defaultBundleName; - private Locale defaultLocale = Locale.getDefault(); - - private String defaultLanguage = Locale.getDefault().getLanguage(); - - private String defaultCountry = Locale.getDefault().getCountry(); - private boolean devMode; + public DefaultI18N() { + initialize(); + } + + public DefaultI18N(String[] bundleNames) { + this.bundleNames = bundleNames != null ? bundleNames.clone() : new String[0]; + initialize(); + } // ---------------------------------------------------------------------- // Accessors // ---------------------------------------------------------------------- public String getDefaultLanguage() { - return defaultLanguage; + return Locale.getDefault().getLanguage(); } public String getDefaultCountry() { - return defaultCountry; + return Locale.getDefault().getCountry(); } public String getDefaultBundleName() { @@ -68,7 +70,7 @@ public String getDefaultBundleName() { } public String[] getBundleNames() { - return (String[]) bundleNames.clone(); + return bundleNames.clone(); } public ResourceBundle getBundle() { @@ -111,25 +113,7 @@ public ResourceBundle getBundle(String bundleName, Locale locale) { // ---------------------------------------------------------------------- if (devMode) { - try { - Class klass = ResourceBundle.getBundle(bundleName).getClass().getSuperclass(); - - Field field = klass.getDeclaredField("cacheList"); - - field.setAccessible(true); - - // SoftCache cache = (SoftCache) field.get( null ); - // - // cache.clear(); - - Object cache = field.get(null); - - cache.getClass().getDeclaredMethod("clear", null).invoke(cache, null); - - field.setAccessible(false); - } catch (Exception e) { - // Intentional - } + ResourceBundle.clearCache(); } if (locale == null) { @@ -139,13 +123,12 @@ public ResourceBundle getBundle(String bundleName, Locale locale) { // Find/retrieve/cache bundle. ResourceBundle rb; - HashMap bundlesByLocale = (HashMap) bundles.get(bundleName); + Map bundlesByLocale = bundles.get(bundleName); if (bundlesByLocale != null) { // Cache of bundles by locale for the named bundle exists. // Check the cache for a bundle corresponding to locale. - rb = (ResourceBundle) bundlesByLocale.get(locale); - + rb = bundlesByLocale.get(locale); if (rb == null) { // Not yet cached. rb = cacheBundle(bundleName, locale); @@ -161,16 +144,15 @@ public ResourceBundle getBundle(String bundleName, Locale locale) { * @see I18N#getLocale(String) */ public Locale getLocale(String header) { - if (!StringUtils.isEmpty(header)) { + if (header != null && !header.isEmpty()) { I18NTokenizer tok = new I18NTokenizer(header); - if (tok.hasNext()) { - return (Locale) tok.next(); + return tok.next(); } } // Couldn't parse locale. - return defaultLocale; + return Locale.getDefault(); } public String getString(String key) { @@ -187,7 +169,6 @@ public String getString(String key, Locale locale) { */ public String getString(String bundleName, Locale locale, String key) { String value; - if (locale == null) { locale = getLocale(null); } @@ -198,11 +179,8 @@ public String getString(String bundleName, Locale locale, String key) { value = getStringOrNull(rb, key); // Look for text in list of default bundles. - if (value == null && bundleNames.length > 0) { - String name; - for (int i = 0; i < bundleNames.length; i++) { - name = bundleNames[i]; - + if (value == null) { + for (String name : bundleNames) { if (!name.equals(bundleName)) { rb = getBundle(name, locale); @@ -218,15 +196,8 @@ public String getString(String bundleName, Locale locale, String key) { } if (value == null) { - String loc = locale.toString(); - - String mesg = - "Noticed missing resource: " + "bundleName=" + bundleName + ", locale=" + loc + ", key=" + key; - - getLogger().debug(mesg); - + log.debug("Noticed missing resource: bundleName={}, locale={}, key={}", bundleName, locale, key); // Just send back the key, we don't need to throw an exception. - value = key; } @@ -234,11 +205,11 @@ public String getString(String bundleName, Locale locale, String key) { } public String format(String key, Object arg1) { - return format(defaultBundleName, defaultLocale, key, new Object[] {arg1}); + return format(defaultBundleName, Locale.getDefault(), key, new Object[] {arg1}); } public String format(String key, Object arg1, Object arg2) { - return format(defaultBundleName, defaultLocale, key, new Object[] {arg1, arg2}); + return format(defaultBundleName, Locale.getDefault(), key, new Object[] {arg1, arg2}); } /** @@ -275,28 +246,15 @@ public String format(String bundleName, Locale locale, String key, Object[] args if (args == null) { args = NO_ARGS; } - - // FIXME: after switching to JDK 1.4, it will be possible to clean - // this up by providing the Locale along with the string in the - // constructor to MessageFormat. Until 1.4, the following workaround - // is required for constructing the format with the appropriate locale: - MessageFormat messageFormat = new MessageFormat(""); - messageFormat.setLocale(locale); - messageFormat.applyPattern(value); - - return messageFormat.format(args); + return new MessageFormat(value, locale).format(args); } /** * Called the first time the Service is used. */ - public void initialize() throws InitializationException { - bundles = new HashMap(); - - defaultLocale = new Locale(defaultLanguage, defaultCountry); - + public void initialize() { + bundles = new HashMap<>(); initializeBundleNames(); - if ("true".equals(System.getProperty("PLEXUS_DEV_MODE"))) { devMode = true; } @@ -307,8 +265,7 @@ public void initialize() throws InitializationException { // ---------------------------------------------------------------------- protected void initializeBundleNames() { - // System.err.println("cfg=" + getConfiguration()); - if (defaultBundleName != null && defaultBundleName.length() > 0) { + if (defaultBundleName != null && !defaultBundleName.isEmpty()) { // Using old-style single bundle name property. if (bundleNames == null || bundleNames.length <= 0) { bundleNames = new String[] {defaultBundleName}; @@ -333,18 +290,15 @@ protected void initializeBundleNames() { * @throws MissingResourceException Bundle not found. */ private synchronized ResourceBundle cacheBundle(String bundleName, Locale locale) throws MissingResourceException { - HashMap bundlesByLocale = (HashMap) bundles.get(bundleName); - - ResourceBundle rb = (bundlesByLocale == null ? null : (ResourceBundle) bundlesByLocale.get(locale)); + Map bundlesByLocale = bundles.get(bundleName); + ResourceBundle rb = (bundlesByLocale == null ? null : bundlesByLocale.get(locale)); if (rb == null) { - bundlesByLocale = (bundlesByLocale == null ? new HashMap(3) : new HashMap(bundlesByLocale)); - + bundlesByLocale = (bundlesByLocale == null ? new HashMap<>(3) : new HashMap<>(bundlesByLocale)); try { rb = ResourceBundle.getBundle(bundleName, locale); } catch (MissingResourceException e) { rb = findBundleByLocale(bundleName, locale, bundlesByLocale); - if (rb == null) { throw (MissingResourceException) e.fillInStackTrace(); } @@ -353,11 +307,8 @@ private synchronized ResourceBundle cacheBundle(String bundleName, Locale locale if (rb != null) { // Cache bundle. bundlesByLocale.put(rb.getLocale(), rb); - - HashMap bundlesByName = new HashMap(bundles); - + Map> bundlesByName = new HashMap<>(bundles); bundlesByName.put(bundleName, bundlesByLocale); - this.bundles = bundlesByName; } } @@ -380,30 +331,31 @@ private synchronized ResourceBundle cacheBundle(String bundleName, Locale locale *

Since we're really just guessing at possible bundles to use, * we don't ever throw MissingResourceException.

*/ - private ResourceBundle findBundleByLocale(String bundleName, Locale locale, Map bundlesByLocale) { + private ResourceBundle findBundleByLocale( + String bundleName, Locale locale, Map bundlesByLocale) { ResourceBundle rb = null; - if (!StringUtils.isNotEmpty(locale.getCountry()) && defaultLanguage.equals(locale.getLanguage())) { - /* - category.debug("Requested language '" + locale.getLanguage() + - "' matches default: Attempting to guess bundle " + - "using default country '" + defaultCountry + '\''); - */ - Locale withDefaultCountry = new Locale(locale.getLanguage(), defaultCountry); - rb = (ResourceBundle) bundlesByLocale.get(withDefaultCountry); + if (locale.getCountry() != null + && !locale.getCountry().isEmpty() + && Locale.getDefault().getLanguage().equals(locale.getLanguage())) { + Locale withDefaultCountry = + new Locale(locale.getLanguage(), Locale.getDefault().getCountry()); + rb = bundlesByLocale.get(withDefaultCountry); if (rb == null) { rb = getBundleIgnoreException(bundleName, withDefaultCountry); } - } else if (!StringUtils.isNotEmpty(locale.getLanguage()) && defaultCountry.equals(locale.getCountry())) { - Locale withDefaultLanguage = new Locale(defaultLanguage, locale.getCountry()); - rb = (ResourceBundle) bundlesByLocale.get(withDefaultLanguage); + } else if (locale.getLanguage() != null + && !locale.getLanguage().isEmpty() + && Locale.getDefault().getCountry().equals(locale.getCountry())) { + Locale withDefaultLanguage = new Locale(Locale.getDefault().getLanguage(), locale.getCountry()); + rb = bundlesByLocale.get(withDefaultLanguage); if (rb == null) { rb = getBundleIgnoreException(bundleName, withDefaultLanguage); } } - if (rb == null && !defaultLocale.equals(locale)) { - rb = getBundleIgnoreException(bundleName, defaultLocale); + if (rb == null && !Locale.getDefault().equals(locale)) { + rb = getBundleIgnoreException(bundleName, Locale.getDefault()); } return rb; diff --git a/src/main/java/org/codehaus/plexus/i18n/I18NTokenizer.java b/src/main/java/org/codehaus/plexus/i18n/I18NTokenizer.java index 0a7a06a..015b55a 100644 --- a/src/main/java/org/codehaus/plexus/i18n/I18NTokenizer.java +++ b/src/main/java/org/codehaus/plexus/i18n/I18NTokenizer.java @@ -16,12 +16,7 @@ * limitations under the License. */ -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.Locale; -import java.util.NoSuchElementException; -import java.util.StringTokenizer; +import java.util.*; /** * Parses the HTTP Accept-Language header as per section @@ -32,7 +27,7 @@ * * TODO Move this class out of here as its purely web related. */ -public class I18NTokenizer implements Iterator { +public class I18NTokenizer implements Iterator { /** * Separates elements of the Accept-Language HTTP * header. @@ -48,12 +43,12 @@ public class I18NTokenizer implements Iterator { * The default quality value for an AcceptLanguage * object. */ - private static final Float DEFAULT_QUALITY = new Float(1.0f); + private static final float DEFAULT_QUALITY = 1.0f; /** * The parsed locales. */ - private ArrayList locales = new ArrayList(3); + private final List locales = new ArrayList<>(3); /** * Parses the Accept-Language header. @@ -76,7 +71,7 @@ public I18NTokenizer(String header) { if ((index = q.indexOf('=')) != -1) { try { acceptLang.quality = Float.valueOf(q.substring(index + 1)); - } catch (NumberFormatException useDefault) { + } catch (NumberFormatException ignored) { } } } @@ -96,7 +91,7 @@ public I18NTokenizer(String header) { } // Sort by quality in descending order. - Collections.sort(locales, Collections.reverseOrder()); + locales.sort(Collections.reverseOrder()); } /** @@ -113,11 +108,11 @@ public boolean hasNext() { * @return The next highest-rated Locale. * @throws NoSuchElementException No more locales. */ - public Object next() { + public Locale next() { if (locales.isEmpty()) { throw new NoSuchElementException(); } - return ((AcceptLanguage) locales.remove(0)).locale; + return locales.remove(0).locale; } /** @@ -131,7 +126,7 @@ public final void remove() { * Struct representing an element of the HTTP * Accept-Language header. */ - private class AcceptLanguage implements Comparable { + private static class AcceptLanguage implements Comparable { /** * The language and country. */ @@ -143,8 +138,8 @@ private class AcceptLanguage implements Comparable { */ Float quality = DEFAULT_QUALITY; - public final int compareTo(Object acceptLang) { - return quality.compareTo(((AcceptLanguage) acceptLang).quality); + public final int compareTo(AcceptLanguage acceptLang) { + return quality.compareTo(acceptLang.quality); } } } diff --git a/src/test/java/org/codehaus/plexus/i18n/DefaultI18NTest.java b/src/test/java/org/codehaus/plexus/i18n/DefaultI18NTest.java index 964faef..bb1b06c 100644 --- a/src/test/java/org/codehaus/plexus/i18n/DefaultI18NTest.java +++ b/src/test/java/org/codehaus/plexus/i18n/DefaultI18NTest.java @@ -54,9 +54,15 @@ * . */ +import javax.inject.Inject; + import java.util.Locale; -import org.codehaus.plexus.PlexusTestCase; +import org.codehaus.plexus.testing.PlexusTest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; /** * Tests the API of the @@ -66,83 +72,73 @@ * @author Daniel Rall * @author Jason van Zyl */ -public class DefaultI18NTest extends PlexusTestCase { +@PlexusTest +public class DefaultI18NTest { + @Inject private I18N i18n; - protected void setUp() throws Exception { - super.setUp(); - + @BeforeEach + protected void setUp() { /* Set an unsupported locale to default to ensure we do not get unexpected matches */ Locale.setDefault(new Locale("jp")); - - i18n = (I18N) lookup(I18N.ROLE); } + @Test public void testLocalization() { String s0 = i18n.getString(null, null, "key1"); - - assertEquals("Unable to retrieve localized text for locale: default", s0, "[] value1"); + assertEquals("[] value1", s0, "Unable to retrieve localized text for locale: default"); String s1 = i18n.getString(null, new Locale("en", "US"), "key2"); - - assertEquals("Unable to retrieve localized text for locale: en-US", s1, "[en_US] value2"); + assertEquals("[en_US] value2", s1, "Unable to retrieve localized text for locale: en-US"); String s2 = i18n.getString("org.codehaus.plexus.i18n.BarBundle", new Locale("ko", "KR"), "key3"); - - assertEquals("Unable to retrieve localized text for locale: ko-KR", s2, "[ko] value3"); + assertEquals("[ko] value3", s2, "Unable to retrieve localized text for locale: ko-KR"); String s3 = i18n.getString("org.codehaus.plexus.i18n.BarBundle", new Locale("ja"), "key1"); - - assertEquals("Unable to fall back from non-existant locale: jp", "[] value1", s3); + assertEquals("[] value1", s3, "Unable to fall back from non-existant locale: jp"); String s4 = i18n.getString("org.codehaus.plexus.i18n.FooBundle", new Locale("fr"), "key3"); - - assertEquals("Unable to retrieve localized text for locale: fr", s4, "[fr] value3"); + assertEquals("[fr] value3", s4, "Unable to retrieve localized text for locale: fr"); String s5 = i18n.getString("org.codehaus.plexus.i18n.FooBundle", new Locale("fr", "FR"), "key3"); - - assertEquals("Unable to retrieve localized text for locale: fr-FR", s5, "[fr] value3"); + assertEquals("[fr] value3", s5, "Unable to retrieve localized text for locale: fr-FR"); String s6 = i18n.getString("org.codehaus.plexus.i18n.i18n", null, "key1"); - - assertEquals("Unable to retrieve localized properties for locale: default", "[] value1", s6); + assertEquals("[] value1", s6, "Unable to retrieve localized properties for locale: default"); Locale old = Locale.getDefault(); Locale.setDefault(Locale.FRENCH); try { String s7 = i18n.getString("org.codehaus.plexus.i18n.i18n", Locale.ENGLISH, "key1"); - - assertEquals("Not picking up new default locale: fr", "[fr] value1", s7); + assertEquals("[fr] value1", s7, "Not picking up new default locale: fr"); String s8 = i18n.getString("org.codehaus.plexus.i18n.i18n", Locale.ITALIAN, "key1"); - - assertEquals("Unable to retrieve localized properties for locale: it", "[it] value1", s8); + assertEquals("[it] value1", s8, "Unable to retrieve localized properties for locale: it"); } finally { Locale.setDefault(old); } } + @Test public void testLocalizedMessagesWithFormatting() { // Format methods String s6 = i18n.format("org.codehaus.plexus.i18n.i18n", null, "thanks.message", "jason"); - - assertEquals(s6, "Thanks jason!"); + assertEquals("Thanks jason!", s6); String s7 = i18n.format("org.codehaus.plexus.i18n.i18n", null, "thanks.message1", "jason", "van zyl"); - - assertEquals(s7, "Thanks jason van zyl!"); + assertEquals("Thanks jason van zyl!", s7); String s8 = i18n.format( "org.codehaus.plexus.i18n.i18n", null, "thanks.message2", new Object[] {"jason", "van zyl"}); - assertEquals(s8, "Thanks jason van zyl!"); + assertEquals("Thanks jason van zyl!", s8); } + @Test public void testLocalizedMessagesWithNonStandardLocale() { String s0 = i18n.getString("name", new Locale("xx")); - assertEquals("plexus", s0); } } diff --git a/src/test/java/org/codehaus/plexus/i18n/I18NTokenizerTest.java b/src/test/java/org/codehaus/plexus/i18n/I18NTokenizerTest.java index 016a4b1..3a5607d 100644 --- a/src/test/java/org/codehaus/plexus/i18n/I18NTokenizerTest.java +++ b/src/test/java/org/codehaus/plexus/i18n/I18NTokenizerTest.java @@ -56,9 +56,9 @@ import java.util.Locale; -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; /** * Test case for the locale tokenizer. @@ -67,29 +67,15 @@ * @author Jason van Zyl * @version $Id: I18NTokenizerTest.java 831 2004-06-16 17:01:12Z jvanzyl $ */ -public class I18NTokenizerTest extends TestCase { - private static final String HEADER = "en, es;q=0.8, zh-TW;q=0.1"; - - public I18NTokenizerTest(String name) { - super(name); - } - - public static Test suite() { - return new TestSuite(I18NTokenizerTest.class); - } - +public class I18NTokenizerTest { + @Test public void testLocaleTokenizer() { - try { - I18NTokenizer tok = new I18NTokenizer(HEADER); - Locale locale = (Locale) tok.next(); - assertEquals("Either wrong language or order parsing: " + locale, locale.getLanguage(), "en"); - locale = (Locale) tok.next(); - assertEquals("Either wrong language or order parsing: " + locale, locale.getLanguage(), "es"); - locale = (Locale) tok.next(); - assertEquals("Either wrong country or order parsing: " + locale, locale.getCountry(), "TW"); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } + I18NTokenizer tok = new I18NTokenizer("en, es;q=0.8, zh-TW;q=0.1"); + Locale locale = tok.next(); + assertEquals("en", locale.getLanguage(), "Either wrong language or order parsing: " + locale); + locale = tok.next(); + assertEquals("es", locale.getLanguage(), "Either wrong language or order parsing: " + locale); + locale = tok.next(); + assertEquals("TW", locale.getCountry(), "Either wrong country or order parsing: " + locale); } }