--- old/src/share/classes/java/util/spi/LocaleServiceProvider.java Fri May 31 16:54:35 2013 +++ new/src/share/classes/java/util/spi/LocaleServiceProvider.java Fri May 31 16:54:33 2013 @@ -128,6 +128,14 @@ * installed SPI providers, and "JRE" represents the locale sensitive services * in the Java Runtime Environment, the locale sensitive services in the SPI * providers are looked up first. + *

+ * There are two other possible locale sensitive service providers, i.e., "CLDR" + * which is a provider based on Unicode Consortium's + * CLDR Project, and "HOST" which is a + * provider that reflects the user's custom settings in the underlying operating + * system. These two providers may not be available, depending on the Java Runtime + * Environment implementation. Specifying "JRE,SPI" is identical to the default + * behavior, which is compatibile with the prior releases. * * @since 1.6 */ --- old/src/share/classes/sun/util/locale/provider/FallbackLocaleProviderAdapter.java Fri May 31 16:54:41 2013 +++ new/src/share/classes/sun/util/locale/provider/FallbackLocaleProviderAdapter.java Fri May 31 16:54:40 2013 @@ -25,6 +25,11 @@ package sun.util.locale.provider; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + /** * FallbackProviderAdapter implementation. * @@ -33,6 +38,22 @@ public class FallbackLocaleProviderAdapter extends JRELocaleProviderAdapter { /** + * Supported language tag set. + */ + private static final Set rootTagSet; + static { + Set tmp = new HashSet<>(); + tmp.add(Locale.ROOT.toLanguageTag()); + rootTagSet = Collections.unmodifiableSet(tmp); + } + + /** + * Fallback provider only provides the ROOT locale data. + */ + private final LocaleResources rootLocaleResources = + new LocaleResources(this, Locale.ROOT); + + /** * Returns the type of this LocaleProviderAdapter */ @Override @@ -39,4 +60,14 @@ public LocaleProviderAdapter.Type getAdapterType() { return Type.FALLBACK; } + + @Override + public LocaleResources getLocaleResources(Locale locale) { + return rootLocaleResources; + } + + @Override + protected Set createLanguageTagSet(String category) { + return rootTagSet; + } } --- old/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Fri May 31 16:54:47 2013 +++ new/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Fri May 31 16:54:46 2013 @@ -34,12 +34,10 @@ import java.text.spi.DateFormatSymbolsProvider; import java.text.spi.DecimalFormatSymbolsProvider; import java.text.spi.NumberFormatProvider; -import java.util.Calendar; import java.util.HashSet; import java.util.Locale; import java.util.Set; import java.util.StringTokenizer; -import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.spi.CalendarDataProvider; --- old/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java Fri May 31 16:54:54 2013 +++ new/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java Fri May 31 16:54:52 2013 @@ -120,6 +120,12 @@ private static LocaleProviderAdapter fallbackLocaleProviderAdapter = null; /** + * Default fallback adapter type, which should return something meaningful in any case. + * This is either JRE or FALLBACK. + */ + static LocaleProviderAdapter.Type defaultLocaleProviderAdapter = null; + + /** * Adapter lookup cache. */ private static ConcurrentMap, ConcurrentMap> @@ -140,13 +146,19 @@ // load adapter if necessary switch (aType) { case CLDR: - cldrLocaleProviderAdapter = new CLDRLocaleProviderAdapter(); + if (cldrLocaleProviderAdapter == null) { + cldrLocaleProviderAdapter = new CLDRLocaleProviderAdapter(); + } break; case HOST: - hostLocaleProviderAdapter = new HostLocaleProviderAdapter(); + if (hostLocaleProviderAdapter == null) { + hostLocaleProviderAdapter = new HostLocaleProviderAdapter(); + } break; } - typeList.add(aType); + if (!typeList.contains(aType)) { + typeList.add(aType); + } } catch (IllegalArgumentException | UnsupportedOperationException e) { // could be caused by the user specifying wrong // provider name or format in the system property @@ -160,11 +172,15 @@ // Append FALLBACK as the last resort. fallbackLocaleProviderAdapter = new FallbackLocaleProviderAdapter(); typeList.add(Type.FALLBACK); + defaultLocaleProviderAdapter = Type.FALLBACK; + } else { + defaultLocaleProviderAdapter = Type.JRE; } } else { // Default preference list typeList.add(Type.JRE); typeList.add(Type.SPI); + defaultLocaleProviderAdapter = Type.JRE; } adapterPreference = Collections.unmodifiableList(typeList); --- old/src/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java Fri May 31 16:55:00 2013 +++ new/src/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java Fri May 31 16:54:59 2013 @@ -127,34 +127,15 @@ private LocaleServiceProviderPool (final Class c) { providerClass = c; - // Add the JRE Locale Data Adapter implementation. - providers.putIfAbsent(LocaleProviderAdapter.Type.JRE, - LocaleProviderAdapter.forJRE().getLocaleServiceProvider(c)); - - // Add the SPI Locale Data Adapter implementation. - LocaleProviderAdapter lda = LocaleProviderAdapter.forType(LocaleProviderAdapter.Type.SPI); - LocaleServiceProvider provider = lda.getLocaleServiceProvider(c); - if (provider != null) { - providers.putIfAbsent(LocaleProviderAdapter.Type.SPI, provider); - } - - // Add the CLDR Locale Data Adapter implementation, if needed. - lda = LocaleProviderAdapter.forType(LocaleProviderAdapter.Type.CLDR); - if (lda != null) { - provider = lda.getLocaleServiceProvider(c); - if (provider != null) { - providers.putIfAbsent(LocaleProviderAdapter.Type.CLDR, provider); + for (LocaleProviderAdapter.Type type : LocaleProviderAdapter.getAdapterPreference()) { + LocaleProviderAdapter lda = LocaleProviderAdapter.forType(type); + if (lda != null) { + LocaleServiceProvider provider = lda.getLocaleServiceProvider(c); + if (provider != null) { + providers.putIfAbsent(type, provider); + } } } - - // Add the Host Locale Data Adapter implementation, if needed. - lda = LocaleProviderAdapter.forType(LocaleProviderAdapter.Type.HOST); - if (lda != null) { - provider = lda.getLocaleServiceProvider(c); - if (provider != null) { - providers.putIfAbsent(LocaleProviderAdapter.Type.HOST, provider); - } - } } static void config(Class caller, String message) { @@ -246,7 +227,8 @@ */ boolean hasProviders() { return providers.size() != 1 || - providers.get(LocaleProviderAdapter.Type.JRE) == null; + (providers.get(LocaleProviderAdapter.Type.JRE) == null && + providers.get(LocaleProviderAdapter.Type.FALLBACK) == null); } /** @@ -296,9 +278,8 @@ // Check whether JRE is the sole locale data provider or not, // and directly call it if it is. if (!hasProviders()) { - return getter.getObject( - (P)providers.get(LocaleProviderAdapter.Type.JRE), - locale, key, params); + return getter.getObject((P)providers.get(LocaleProviderAdapter.defaultLocaleProviderAdapter), + locale, key, params); } List lookupLocales = getLookupLocales(locale); --- old/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java Fri May 31 16:55:06 2013 +++ new/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java Fri May 31 16:55:05 2013 @@ -48,7 +48,6 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.spi.CalendarDataProvider; -import java.util.spi.CalendarNameProvider; import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; import sun.util.spi.CalendarProvider; @@ -362,32 +361,6 @@ return 0; } }; - } - - public static CalendarNameProvider getCalendarNameProvider() { - return new CalendarNameProvider() { - @Override - public Locale[] getAvailableLocales() { - return getSupportedCalendarLocales(); - } - - @Override - public boolean isSupportedLocale(Locale locale) { - return isSupportedCalendarLocale(locale); - } - - @Override - public String getDisplayName(String calType, int field, int value, - int style, Locale locale) { - return null; - } - - @Override - public Map getDisplayNames(String calType, - int field, int style, Locale locale) { - return null; - } - }; } public static CalendarProvider getCalendarProvider() { --- old/test/java/util/Locale/LocaleProviders.java Fri May 31 16:55:21 2013 +++ new/test/java/util/Locale/LocaleProviders.java Fri May 31 16:55:19 2013 @@ -64,6 +64,10 @@ bug8013086Test(args[1], args[2]); break; + case "bug8013903Test": + bug8013903Test(); + break; + default: throw new RuntimeException("Test method '"+methodName+"' not found."); } @@ -195,4 +199,30 @@ // ParseException is fine in this test, as it's not "UTC" } } + + static void bug8013903Test() { + if (System.getProperty("os.name").startsWith("Windows")) { + Date sampleDate = new Date(0x10000000000L); + String fallbackResult = "Heisei 16.Nov.03 (Wed) AM 11:53:47"; + String jreResult = "\u5e73\u6210 16.11.03 (\u6c34) \u5348\u524d 11:53:47"; + Locale l = new Locale("ja", "JP", "JP"); + SimpleDateFormat sdf = new SimpleDateFormat("GGGG yyyy.MMM.dd '('E')' a hh:mm:ss", l); + String result = sdf.format(sampleDate); + System.out.println(result); + if (LocaleProviderAdapter.getAdapterPreference() + .contains(LocaleProviderAdapter.Type.JRE)) { + if (!jreResult.equals(result)) { + throw new RuntimeException("Format failed. result: \"" + + result + "\", expected: \"" + jreResult); + } + } else { + // should be FALLBACK, as Windows HOST does not return + // display names + if (!fallbackResult.equals(result)) { + throw new RuntimeException("Format failed. result: \"" + + result + "\", expected: \"" + fallbackResult); + } + } + } + } } --- old/test/java/util/Locale/LocaleProviders.sh Fri May 31 16:55:27 2013 +++ new/test/java/util/Locale/LocaleProviders.sh Fri May 31 16:55:25 2013 @@ -24,7 +24,7 @@ # # @test # @bug 6336885 7196799 7197573 7198834 8000245 8000615 8001440 8010666 -# 8013086 8013233 +# 8013086 8013233 8013903 # @summary tests for "java.locale.providers" system property # @compile -XDignore.symbol.file LocaleProviders.java # @run shell/timeout=600 LocaleProviders.sh @@ -299,5 +299,19 @@ PARAM2=JP PARAM3= runTest + +# testing 8013903 fix. (Windows only) +METHODNAME=bug8013903Test +PREFLIST=HOST,JRE +PARAM1= +PARAM2= +PARAM3= +runTest +METHODNAME=bug8013903Test +PREFLIST=HOST +PARAM1= +PARAM2= +PARAM3= +runTest exit $result