# HG changeset patch # User naoto # Date 1533141236 25200 # Node ID 04183bf08bff137b501532a68658df69b15441c8 # Parent b095f437af223eeb122a06091b4ad3b6a8d7282e 8208080: Locale extensions via Service provider is not working for region extensions Reviewed-by: rriggs, nishjain diff -r b095f437af22 -r 04183bf08bff src/java.base/share/classes/sun/util/locale/provider/CalendarDataUtility.java --- a/src/java.base/share/classes/sun/util/locale/provider/CalendarDataUtility.java Wed Aug 01 18:02:25 2018 +0530 +++ b/src/java.base/share/classes/sun/util/locale/provider/CalendarDataUtility.java Wed Aug 01 09:33:56 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ public class CalendarDataUtility { public static final String FIRST_DAY_OF_WEEK = "firstDayOfWeek"; public static final String MINIMAL_DAYS_IN_FIRST_WEEK = "minimalDaysInFirstWeek"; + private static final Locale.Builder OVERRIDE_BUILDER = new Locale.Builder(); // No instantiation private CalendarDataUtility() { @@ -144,7 +145,9 @@ rg.charAt(1) >= 0x0041 && rg.charAt(1) <= 0x005A && rg.substring(2).equals("ZZZZ")) { - override = new Locale.Builder().setLocale(l) + override = OVERRIDE_BUILDER + .clear() + .setLocale(l) .setRegion(rg.substring(0, 2)) .build(); } diff -r b095f437af22 -r 04183bf08bff src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java --- a/src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java Wed Aug 01 18:02:25 2018 +0530 +++ b/src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java Wed Aug 01 09:33:56 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ import java.text.spi.DateFormatSymbolsProvider; import java.text.spi.DecimalFormatSymbolsProvider; import java.text.spi.NumberFormatProvider; +import java.util.Arrays; import java.util.Locale; import java.util.Map; import java.util.ServiceLoader; @@ -110,22 +111,52 @@ * Delegate interface. All the implementations have to have the class name * following "Delegate" convention. */ - interface Delegate

{ - public void addImpl(P impl); - public P getImpl(Locale locale); - } - - /* - * Obtain the real SPI implementation, using locale fallback - */ - private static

P getImpl(Map map, Locale locale) { - for (Locale l : LocaleServiceProviderPool.getLookupLocales(locale)) { - P ret = map.get(l); - if (ret != null) { - return ret; + private interface Delegate

{ + default public void addImpl(P impl) { + for (Locale l : impl.getAvailableLocales()) { + getDelegateMap().putIfAbsent(l, impl); } } - return null; + + /* + * Obtain the real SPI implementation, using locale fallback + */ + default public P getImpl(Locale locale) { + for (Locale l : LocaleServiceProviderPool.getLookupLocales(locale.stripExtensions())) { + P ret = getDelegateMap().get(l); + if (ret != null) { + return ret; + } + } + return null; + } + + public Map getDelegateMap(); + + default public Locale[] getAvailableLocalesDelegate() { + return getDelegateMap().keySet().stream().toArray(Locale[]::new); + } + + default public boolean isSupportedLocaleDelegate(Locale locale) { + Map map = getDelegateMap(); + Locale override = CalendarDataUtility.findRegionOverride(locale); + + // First, call the method with extensions (if any) + P impl = map.get(override); + if (impl != null) { + return impl.isSupportedLocale(override); + } else { + // The default behavior + Locale overrideNoExt = override.stripExtensions(); + impl = map.get(overrideNoExt); + if (impl != null) { + return Arrays.stream(impl.getAvailableLocales()) + .anyMatch(overrideNoExt::equals); + } + } + + return false; + } } /* @@ -133,50 +164,47 @@ */ static class BreakIteratorProviderDelegate extends BreakIteratorProvider implements Delegate { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); @Override - public void addImpl(BreakIteratorProvider impl) { - for (Locale l : impl.getAvailableLocales()) { - map.putIfAbsent(l, impl); - } - } - - @Override - public BreakIteratorProvider getImpl(Locale locale) { - return SPILocaleProviderAdapter.getImpl(map, locale); + public Map getDelegateMap() { + return map; } @Override public Locale[] getAvailableLocales() { - return map.keySet().toArray(new Locale[0]); + return getAvailableLocalesDelegate(); } @Override public boolean isSupportedLocale(Locale locale) { - return map.containsKey(locale); + return isSupportedLocaleDelegate(locale); } @Override public BreakIterator getWordInstance(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); BreakIteratorProvider bip = getImpl(locale); return bip.getWordInstance(locale); } @Override public BreakIterator getLineInstance(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); BreakIteratorProvider bip = getImpl(locale); return bip.getLineInstance(locale); } @Override public BreakIterator getCharacterInstance(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); BreakIteratorProvider bip = getImpl(locale); return bip.getCharacterInstance(locale); } @Override public BreakIterator getSentenceInstance(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); BreakIteratorProvider bip = getImpl(locale); return bip.getSentenceInstance(locale); } @@ -184,32 +212,26 @@ } static class CollatorProviderDelegate extends CollatorProvider implements Delegate { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); @Override - public void addImpl(CollatorProvider impl) { - for (Locale l : impl.getAvailableLocales()) { - map.putIfAbsent(l, impl); - } - } - - @Override - public CollatorProvider getImpl(Locale locale) { - return SPILocaleProviderAdapter.getImpl(map, locale); + public Map getDelegateMap() { + return map; } @Override public Locale[] getAvailableLocales() { - return map.keySet().toArray(new Locale[0]); + return getAvailableLocalesDelegate(); } @Override public boolean isSupportedLocale(Locale locale) { - return map.containsKey(locale); + return isSupportedLocaleDelegate(locale); } @Override public Collator getInstance(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); CollatorProvider cp = getImpl(locale); return cp.getInstance(locale); } @@ -217,44 +239,40 @@ static class DateFormatProviderDelegate extends DateFormatProvider implements Delegate { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); @Override - public void addImpl(DateFormatProvider impl) { - for (Locale l : impl.getAvailableLocales()) { - map.putIfAbsent(l, impl); - } - } - - @Override - public DateFormatProvider getImpl(Locale locale) { - return SPILocaleProviderAdapter.getImpl(map, locale); + public Map getDelegateMap() { + return map; } @Override public Locale[] getAvailableLocales() { - return map.keySet().toArray(new Locale[0]); + return getAvailableLocalesDelegate(); } @Override public boolean isSupportedLocale(Locale locale) { - return map.containsKey(locale); + return isSupportedLocaleDelegate(locale); } @Override public DateFormat getTimeInstance(int style, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); DateFormatProvider dfp = getImpl(locale); return dfp.getTimeInstance(style, locale); } @Override public DateFormat getDateInstance(int style, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); DateFormatProvider dfp = getImpl(locale); return dfp.getDateInstance(style, locale); } @Override public DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); DateFormatProvider dfp = getImpl(locale); return dfp.getDateTimeInstance(dateStyle, timeStyle, locale); } @@ -262,32 +280,26 @@ static class DateFormatSymbolsProviderDelegate extends DateFormatSymbolsProvider implements Delegate { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); @Override - public void addImpl(DateFormatSymbolsProvider impl) { - for (Locale l : impl.getAvailableLocales()) { - map.putIfAbsent(l, impl); - } - } - - @Override - public DateFormatSymbolsProvider getImpl(Locale locale) { - return SPILocaleProviderAdapter.getImpl(map, locale); + public Map getDelegateMap() { + return map; } @Override public Locale[] getAvailableLocales() { - return map.keySet().toArray(new Locale[0]); + return getAvailableLocalesDelegate(); } @Override public boolean isSupportedLocale(Locale locale) { - return map.containsKey(locale); + return isSupportedLocaleDelegate(locale); } @Override public DateFormatSymbols getInstance(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); DateFormatSymbolsProvider dfsp = getImpl(locale); return dfsp.getInstance(locale); } @@ -295,32 +307,26 @@ static class DecimalFormatSymbolsProviderDelegate extends DecimalFormatSymbolsProvider implements Delegate { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); @Override - public void addImpl(DecimalFormatSymbolsProvider impl) { - for (Locale l : impl.getAvailableLocales()) { - map.putIfAbsent(l, impl); - } - } - - @Override - public DecimalFormatSymbolsProvider getImpl(Locale locale) { - return SPILocaleProviderAdapter.getImpl(map, locale); + public Map getDelegateMap() { + return map; } @Override public Locale[] getAvailableLocales() { - return map.keySet().toArray(new Locale[0]); + return getAvailableLocalesDelegate(); } @Override public boolean isSupportedLocale(Locale locale) { - return map.containsKey(locale); + return isSupportedLocaleDelegate(locale); } @Override public DecimalFormatSymbols getInstance(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); DecimalFormatSymbolsProvider dfsp = getImpl(locale); return dfsp.getInstance(locale); } @@ -328,50 +334,47 @@ static class NumberFormatProviderDelegate extends NumberFormatProvider implements Delegate { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); @Override - public void addImpl(NumberFormatProvider impl) { - for (Locale l : impl.getAvailableLocales()) { - map.putIfAbsent(l, impl); - } - } - - @Override - public NumberFormatProvider getImpl(Locale locale) { - return SPILocaleProviderAdapter.getImpl(map, locale); + public Map getDelegateMap() { + return map; } @Override public Locale[] getAvailableLocales() { - return map.keySet().toArray(new Locale[0]); + return getAvailableLocalesDelegate(); } @Override public boolean isSupportedLocale(Locale locale) { - return map.containsKey(locale); + return isSupportedLocaleDelegate(locale); } @Override public NumberFormat getCurrencyInstance(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); NumberFormatProvider nfp = getImpl(locale); return nfp.getCurrencyInstance(locale); } @Override public NumberFormat getIntegerInstance(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); NumberFormatProvider nfp = getImpl(locale); return nfp.getIntegerInstance(locale); } @Override public NumberFormat getNumberInstance(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); NumberFormatProvider nfp = getImpl(locale); return nfp.getNumberInstance(locale); } @Override public NumberFormat getPercentInstance(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); NumberFormatProvider nfp = getImpl(locale); return nfp.getPercentInstance(locale); } @@ -379,38 +382,33 @@ static class CalendarDataProviderDelegate extends CalendarDataProvider implements Delegate { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); @Override - public void addImpl(CalendarDataProvider impl) { - for (Locale l : impl.getAvailableLocales()) { - map.putIfAbsent(l, impl); - } - } - - @Override - public CalendarDataProvider getImpl(Locale locale) { - return SPILocaleProviderAdapter.getImpl(map, locale); + public Map getDelegateMap() { + return map; } @Override public Locale[] getAvailableLocales() { - return map.keySet().toArray(new Locale[0]); + return getAvailableLocalesDelegate(); } @Override public boolean isSupportedLocale(Locale locale) { - return map.containsKey(locale); + return isSupportedLocaleDelegate(locale); } @Override public int getFirstDayOfWeek(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); CalendarDataProvider cdp = getImpl(locale); return cdp.getFirstDayOfWeek(locale); } @Override public int getMinimalDaysInFirstWeek(Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); CalendarDataProvider cdp = getImpl(locale); return cdp.getMinimalDaysInFirstWeek(locale); } @@ -418,34 +416,28 @@ static class CalendarNameProviderDelegate extends CalendarNameProvider implements Delegate { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); @Override - public void addImpl(CalendarNameProvider impl) { - for (Locale l : impl.getAvailableLocales()) { - map.putIfAbsent(l, impl); - } - } - - @Override - public CalendarNameProvider getImpl(Locale locale) { - return SPILocaleProviderAdapter.getImpl(map, locale); + public Map getDelegateMap() { + return map; } @Override public Locale[] getAvailableLocales() { - return map.keySet().toArray(new Locale[0]); + return getAvailableLocalesDelegate(); } @Override public boolean isSupportedLocale(Locale locale) { - return map.containsKey(locale); + return isSupportedLocaleDelegate(locale); } @Override public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); CalendarNameProvider cdp = getImpl(locale); return cdp.getDisplayName(calendarType, field, value, style, locale); } @@ -454,6 +446,7 @@ public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); CalendarNameProvider cdp = getImpl(locale); return cdp.getDisplayNames(calendarType, field, style, locale); } @@ -461,38 +454,33 @@ static class CurrencyNameProviderDelegate extends CurrencyNameProvider implements Delegate { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); @Override - public void addImpl(CurrencyNameProvider impl) { - for (Locale l : impl.getAvailableLocales()) { - map.putIfAbsent(l, impl); - } - } - - @Override - public CurrencyNameProvider getImpl(Locale locale) { - return SPILocaleProviderAdapter.getImpl(map, locale); + public Map getDelegateMap() { + return map; } @Override public Locale[] getAvailableLocales() { - return map.keySet().toArray(new Locale[0]); + return getAvailableLocalesDelegate(); } @Override public boolean isSupportedLocale(Locale locale) { - return map.containsKey(locale); + return isSupportedLocaleDelegate(locale); } @Override public String getSymbol(String currencyCode, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); CurrencyNameProvider cnp = getImpl(locale); return cnp.getSymbol(currencyCode, locale); } @Override public String getDisplayName(String currencyCode, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); CurrencyNameProvider cnp = getImpl(locale); return cnp.getDisplayName(currencyCode, locale); } @@ -500,62 +488,61 @@ static class LocaleNameProviderDelegate extends LocaleNameProvider implements Delegate { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); @Override - public void addImpl(LocaleNameProvider impl) { - for (Locale l : impl.getAvailableLocales()) { - map.putIfAbsent(l, impl); - } - } - - @Override - public LocaleNameProvider getImpl(Locale locale) { - return SPILocaleProviderAdapter.getImpl(map, locale); + public Map getDelegateMap() { + return map; } @Override public Locale[] getAvailableLocales() { - return map.keySet().toArray(new Locale[0]); + return getAvailableLocalesDelegate(); } @Override public boolean isSupportedLocale(Locale locale) { - return map.containsKey(locale); + return isSupportedLocaleDelegate(locale); } @Override public String getDisplayLanguage(String languageCode, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); LocaleNameProvider lnp = getImpl(locale); return lnp.getDisplayLanguage(languageCode, locale); } @Override public String getDisplayScript(String scriptCode, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); LocaleNameProvider lnp = getImpl(locale); return lnp.getDisplayScript(scriptCode, locale); } @Override public String getDisplayCountry(String countryCode, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); LocaleNameProvider lnp = getImpl(locale); return lnp.getDisplayCountry(countryCode, locale); } @Override public String getDisplayVariant(String variant, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); LocaleNameProvider lnp = getImpl(locale); return lnp.getDisplayVariant(variant, locale); } @Override public String getDisplayUnicodeExtensionKey(String key, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); LocaleNameProvider lnp = getImpl(locale); return lnp.getDisplayUnicodeExtensionKey(key, locale); } @Override public String getDisplayUnicodeExtensionType(String extType, String key, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); LocaleNameProvider lnp = getImpl(locale); return lnp.getDisplayUnicodeExtensionType(extType, key, locale); } @@ -563,38 +550,33 @@ static class TimeZoneNameProviderDelegate extends TimeZoneNameProvider implements Delegate { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final Map map = new ConcurrentHashMap<>(); @Override - public void addImpl(TimeZoneNameProvider impl) { - for (Locale l : impl.getAvailableLocales()) { - map.putIfAbsent(l, impl); - } - } - - @Override - public TimeZoneNameProvider getImpl(Locale locale) { - return SPILocaleProviderAdapter.getImpl(map, locale); + public Map getDelegateMap() { + return map; } @Override public Locale[] getAvailableLocales() { - return map.keySet().toArray(new Locale[0]); + return getAvailableLocalesDelegate(); } @Override public boolean isSupportedLocale(Locale locale) { - return map.containsKey(locale); + return isSupportedLocaleDelegate(locale); } @Override public String getDisplayName(String ID, boolean daylight, int style, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); TimeZoneNameProvider tznp = getImpl(locale); return tznp.getDisplayName(ID, daylight, style, locale); } @Override public String getGenericDisplayName(String ID, int style, Locale locale) { + locale = CalendarDataUtility.findRegionOverride(locale); TimeZoneNameProvider tznp = getImpl(locale); return tznp.getGenericDisplayName(ID, style, locale); } diff -r b095f437af22 -r 04183bf08bff test/jdk/java/util/Locale/bcp47u/spi/DateFormatSymbolsProviderTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/util/Locale/bcp47u/spi/DateFormatSymbolsProviderTests.java Wed Aug 01 09:33:56 2018 -0700 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8208080 + * @summary Tests DateFormatSymbols provider implementations + * @library provider + * @build provider/module-info provider/foo.DateFormatSymbolsProviderImpl + * @run main/othervm -Djava.locale.providers=SPI,CLDR DateFormatSymbolsProviderTests + */ + +import java.text.DateFormatSymbols; +import java.util.Locale; +import java.util.Map; + +/** + * Test DateFormatSymbolsProvider SPI with BCP47 U extensions + */ +public class DateFormatSymbolsProviderTests { + private static final Map data = Map.of( + Locale.forLanguageTag("en-AA"), "foo", + Locale.forLanguageTag("en-US-u-rg-aazzzz"), "foo", + Locale.forLanguageTag("en-US-u-ca-japanese"), "bar" + ); + + public static void main(String... args) { + data.forEach((l, e) -> { + DateFormatSymbols dfs = DateFormatSymbols.getInstance(l); + String[] months = dfs.getMonths(); + System.out.printf("January string for locale %s is %s.%n", l.toString(), months[0]); + if (!months[0].equals(e)) { + throw new RuntimeException("DateFormatSymbols provider is not called for" + l); + } + }); + } +} diff -r b095f437af22 -r 04183bf08bff test/jdk/java/util/Locale/bcp47u/spi/provider/foo/DateFormatSymbolsProviderImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/util/Locale/bcp47u/spi/provider/foo/DateFormatSymbolsProviderImpl.java Wed Aug 01 09:33:56 2018 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package foo; + +import java.text.DateFormatSymbols; +import java.text.spi.DateFormatSymbolsProvider; +import java.util.Locale; + +/* + * Implements DateFormatSymbolsProvider SPI, in order to check if the + * extensions work correctly. + */ +public class DateFormatSymbolsProviderImpl extends DateFormatSymbolsProvider { + private static final Locale AA = Locale.forLanguageTag("en-AA"); + private static final Locale USJCAL = Locale.forLanguageTag("en-US-u-ca-japanese"); + private static final Locale[] avail = {AA, Locale.US}; + + @Override + public Locale[] getAvailableLocales() { + return avail; + } + + @Override + public boolean isSupportedLocale(Locale l) { + // Overriding to check the relation between + // isSupportedLocale/getAvailableLocales works correctly + if (l.equals(AA)) { + // delegates to super, as if isSupportedLocale didn't exist. + return super.isSupportedLocale(l); + } else { + return (l.equals(USJCAL)); + } + } + + @Override + public DateFormatSymbols getInstance(Locale l) { + return new MyDateFormatSymbols(l); + } + + class MyDateFormatSymbols extends DateFormatSymbols { + Locale locale; + + public MyDateFormatSymbols(Locale l) { + super(l); + locale = l; + } + + @Override + public String[] getMonths() { + String[] ret = super.getMonths(); + // replace the first item with some unique value + if (locale.stripExtensions().equals(AA)) { + ret[0] = "foo"; + } else if (locale.equals(USJCAL)) { + ret[0] = "bar"; + } else { + throw new RuntimeException("Unsupported locale: " + locale); + } + return ret; + } + } +} diff -r b095f437af22 -r 04183bf08bff test/jdk/java/util/Locale/bcp47u/spi/provider/module-info.java --- a/test/jdk/java/util/Locale/bcp47u/spi/provider/module-info.java Wed Aug 01 18:02:25 2018 +0530 +++ b/test/jdk/java/util/Locale/bcp47u/spi/provider/module-info.java Wed Aug 01 09:33:56 2018 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,5 +23,6 @@ module provider { exports foo; + provides java.text.spi.DateFormatSymbolsProvider with foo.DateFormatSymbolsProviderImpl; provides java.util.spi.LocaleNameProvider with foo.LocaleNameProviderImpl; }