src/share/classes/sun/util/locale/provider/LocaleServiceProviderPool.java
Print this page
rev 5696 : 6336885: RFE: Locale Data Deployment Enhancements
4609153: Provide locale data for Indic locales
5104387: Support for gl_ES locale (galician language)
6337471: desktop/system locale preferences support
7056139: (cal) SPI support for locale-dependent Calendar parameters
7058206: Provide CalendarData SPI for week params and display field value names
7073852: Support multiple scripts for digits and decimal symbols per locale
7079560: [Fmt-Da] Context dependent month names support in SimpleDateFormat
7171324: getAvailableLocales() of locale sensitive services should return the actual availability of locales
7151414: (cal) Support calendar type identification
7168528: LocaleServiceProvider needs to be aware of Locale extensions
7171372: (cal) locale's default Calendar should be created if unknown calendar is specified
Summary: JEP 127: Improve Locale Data Packaging and Adopt Unicode CLDR Data (part 1 w/o packaging changes. by Naoto Sato and Masayoshi Okutsu)
*** 1,7 ****
/*
! * Copyright (c) 2005, 2010, 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. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 2005, 2012, 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. Oracle designates this
*** 21,58 ****
* 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 sun.util;
- import java.security.AccessController;
- import java.security.PrivilegedActionException;
- import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.IllformedLocaleException;
- import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Locale.Builder;
- import java.util.Map;
import java.util.ResourceBundle.Control;
- import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.spi.LocaleServiceProvider;
-
import sun.util.logging.PlatformLogger;
- import sun.util.resources.LocaleData;
- import sun.util.resources.OpenListResourceBundle;
/**
* An instance of this class holds a set of the third party implementations of a particular
* locale sensitive service, such as {@link java.util.spi.LocaleNameProvider}.
*
*/
public final class LocaleServiceProviderPool {
/**
* A Map that holds singleton instances of this class. Each instance holds a
--- 21,52 ----
* 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 sun.util.locale.provider;
import java.util.ArrayList;
+ import java.util.Collections;
import java.util.HashSet;
import java.util.IllformedLocaleException;
import java.util.List;
import java.util.Locale;
import java.util.Locale.Builder;
import java.util.ResourceBundle.Control;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.spi.LocaleServiceProvider;
import sun.util.logging.PlatformLogger;
/**
* An instance of this class holds a set of the third party implementations of a particular
* locale sensitive service, such as {@link java.util.spi.LocaleNameProvider}.
*
+ * @author Naoto Sato
+ * @author Masayoshi Okutsu
*/
public final class LocaleServiceProviderPool {
/**
* A Map that holds singleton instances of this class. Each instance holds a
*** 60,110 ****
*/
private static ConcurrentMap<Class<? extends LocaleServiceProvider>, LocaleServiceProviderPool> poolOfPools =
new ConcurrentHashMap<>();
/**
! * A Set containing locale service providers that implement the
! * specified provider SPI
*/
! private Set<LocaleServiceProvider> providers =
! new LinkedHashSet<LocaleServiceProvider>();
/**
* A Map that retains Locale->provider mapping
*/
! private Map<Locale, LocaleServiceProvider> providersCache =
! new ConcurrentHashMap<Locale, LocaleServiceProvider>();
/**
* Available locales for this locale sensitive service. This also contains
* JRE's available locales
*/
private Set<Locale> availableLocales = null;
/**
! * Available locales within this JRE. Currently this is declared as
! * static. This could be non-static later, so that they could have
! * different sets for each locale sensitive services.
*/
! private static volatile List<Locale> availableJRELocales = null;
/**
! * Provider locales for this locale sensitive service.
*/
! private Set<Locale> providerLocales = null;
/**
- * Special locale for ja_JP with Japanese calendar
- */
- private static Locale locale_ja_JP_JP = new Locale("ja", "JP", "JP");
-
- /**
- * Special locale for th_TH with Thai numbering system
- */
- private static Locale locale_th_TH_TH = new Locale("th", "TH", "TH");
-
- /**
* A factory method that returns a singleton instance
*/
public static LocaleServiceProviderPool getPool(Class<? extends LocaleServiceProvider> providerClass) {
LocaleServiceProviderPool pool = poolOfPools.get(providerClass);
if (pool == null) {
--- 54,109 ----
*/
private static ConcurrentMap<Class<? extends LocaleServiceProvider>, LocaleServiceProviderPool> poolOfPools =
new ConcurrentHashMap<>();
/**
! * A Map containing locale service providers that implement the
! * specified provider SPI, keyed by a LocaleProviderAdapter.Type
*/
! private ConcurrentMap<LocaleProviderAdapter.Type, LocaleServiceProvider> providers =
! new ConcurrentHashMap<>();
/**
* A Map that retains Locale->provider mapping
*/
! private ConcurrentMap<Locale, List<LocaleProviderAdapter.Type>> providersCache =
! new ConcurrentHashMap<>();
/**
* Available locales for this locale sensitive service. This also contains
* JRE's available locales
*/
private Set<Locale> availableLocales = null;
/**
! * Provider class
*/
! private Class<? extends LocaleServiceProvider> providerClass;
/**
! * Array of all Locale Sensitive SPI classes.
! *
! * We know "spiClasses" contains classes that extends LocaleServiceProvider,
! * but generic array creation is not allowed, thus the "unchecked" warning
! * is suppressed here.
*/
! @SuppressWarnings("unchecked")
! static final Class<LocaleServiceProvider>[] spiClasses =
! (Class<LocaleServiceProvider>[]) new Class<?>[] {
! java.text.spi.BreakIteratorProvider.class,
! java.text.spi.CollatorProvider.class,
! java.text.spi.DateFormatProvider.class,
! java.text.spi.DateFormatSymbolsProvider.class,
! java.text.spi.DecimalFormatSymbolsProvider.class,
! java.text.spi.NumberFormatProvider.class,
! java.util.spi.CurrencyNameProvider.class,
! java.util.spi.LocaleNameProvider.class,
! java.util.spi.TimeZoneNameProvider.class,
! java.util.spi.CalendarDataProvider.class
! };
/**
* A factory method that returns a singleton instance
*/
public static LocaleServiceProviderPool getPool(Class<? extends LocaleServiceProvider> providerClass) {
LocaleServiceProviderPool pool = poolOfPools.get(providerClass);
if (pool == null) {
*** 123,196 ****
* The sole constructor.
*
* @param c class of the locale sensitive service
*/
private LocaleServiceProviderPool (final Class<? extends LocaleServiceProvider> c) {
! try {
! AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
! public Object run() {
! for (LocaleServiceProvider provider : ServiceLoader.loadInstalled(c)) {
! providers.add(provider);
}
! return null;
}
- });
- } catch (PrivilegedActionException e) {
- config(e.toString());
}
}
! private static void config(String message) {
! PlatformLogger logger = PlatformLogger.getLogger("sun.util.LocaleServiceProviderPool");
logger.config(message);
}
/**
* Lazy loaded set of available locales.
* Loading all locales is a very long operation.
- *
- * We know "providerClasses" contains classes that extends LocaleServiceProvider,
- * but generic array creation is not allowed, thus the "unchecked" warning
- * is suppressed here.
*/
private static class AllAvailableLocales {
/**
* Available locales for all locale sensitive services.
* This also contains JRE's available locales
*/
static final Locale[] allAvailableLocales;
static {
! @SuppressWarnings("unchecked")
! Class<LocaleServiceProvider>[] providerClasses =
! (Class<LocaleServiceProvider>[]) new Class<?>[] {
! java.text.spi.BreakIteratorProvider.class,
! java.text.spi.CollatorProvider.class,
! java.text.spi.DateFormatProvider.class,
! java.text.spi.DateFormatSymbolsProvider.class,
! java.text.spi.DecimalFormatSymbolsProvider.class,
! java.text.spi.NumberFormatProvider.class,
! java.util.spi.CurrencyNameProvider.class,
! java.util.spi.LocaleNameProvider.class,
! java.util.spi.TimeZoneNameProvider.class };
!
! // Normalize locales for look up
! Locale[] allLocales = LocaleData.getAvailableLocales();
! Set<Locale> all = new HashSet<Locale>(allLocales.length);
! for (Locale locale : allLocales) {
! all.add(getLookupLocale(locale));
! }
!
! for (Class<LocaleServiceProvider> providerClass : providerClasses) {
LocaleServiceProviderPool pool =
! LocaleServiceProviderPool.getPool(providerClass);
! all.addAll(pool.getProviderLocales());
}
allAvailableLocales = all.toArray(new Locale[0]);
}
}
/**
* Returns an array of available locales for all the provider classes.
* This array is a merged array of all the locales that are provided by each
* provider, including the JRE.
--- 122,194 ----
* The sole constructor.
*
* @param c class of the locale sensitive service
*/
private LocaleServiceProviderPool (final Class<? extends LocaleServiceProvider> 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);
}
}
+
+ // 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<? extends Object> caller, String message) {
! PlatformLogger logger = PlatformLogger.getLogger(caller.getCanonicalName());
logger.config(message);
}
/**
* Lazy loaded set of available locales.
* Loading all locales is a very long operation.
*/
private static class AllAvailableLocales {
/**
* Available locales for all locale sensitive services.
* This also contains JRE's available locales
*/
static final Locale[] allAvailableLocales;
static {
! Set<Locale> all = new HashSet<>();
! for (Class<? extends LocaleServiceProvider> c : spiClasses) {
LocaleServiceProviderPool pool =
! LocaleServiceProviderPool.getPool(c);
! all.addAll(pool.getAvailableLocaleList());
}
allAvailableLocales = all.toArray(new Locale[0]);
}
+
+ // No instantiation
+ private AllAvailableLocales() {
}
+ }
/**
* Returns an array of available locales for all the provider classes.
* This array is a merged array of all the locales that are provided by each
* provider, including the JRE.
*** 206,292 ****
* merged array of all the locales that are provided by each
* provider, including the JRE.
*
* @return an array of the available locales
*/
! public synchronized Locale[] getAvailableLocales() {
! if (availableLocales == null) {
! availableLocales = new HashSet<Locale>(getJRELocales());
! if (hasProviders()) {
! availableLocales.addAll(getProviderLocales());
! }
! }
! Locale[] tmp = new Locale[availableLocales.size()];
! availableLocales.toArray(tmp);
return tmp;
}
! /**
! * Returns an array of available locales (already normalized
! * for service lookup) from providers.
! * Note that this method does not return a defensive copy.
! *
! * @return list of the provider locales
! */
! private synchronized Set<Locale> getProviderLocales() {
! if (providerLocales == null) {
! providerLocales = new HashSet<Locale>();
! if (hasProviders()) {
! for (LocaleServiceProvider lsp : providers) {
Locale[] locales = lsp.getAvailableLocales();
for (Locale locale: locales) {
! providerLocales.add(getLookupLocale(locale));
}
}
- }
- }
- return providerLocales;
- }
! /**
! * Returns whether any provider for this locale sensitive
! * service is available or not.
! *
! * @return true if any provider is available
! */
! public boolean hasProviders() {
! return !providers.isEmpty();
}
! /**
! * Returns an array of available locales (already normalized for
! * service lookup) supported by the JRE.
! * Note that this method does not return a defensive copy.
! *
! * @return list of the available JRE locales
! */
! private List<Locale> getJRELocales() {
! if (availableJRELocales == null) {
! synchronized (LocaleServiceProviderPool.class) {
! if (availableJRELocales == null) {
! Locale[] allLocales = LocaleData.getAvailableLocales();
! List<Locale> tmpList = new ArrayList<>(allLocales.length);
! for (Locale locale : allLocales) {
! tmpList.add(getLookupLocale(locale));
}
- availableJRELocales = tmpList;
- }
- }
- }
- return availableJRELocales;
- }
/**
! * Returns whether the given locale is supported by the JRE.
*
! * @param locale the locale to test.
! * @return true, if the locale is supported by the JRE. false
! * otherwise.
*/
! private boolean isJRESupported(Locale locale) {
! List<Locale> locales = getJRELocales();
! return locales.contains(getLookupLocale(locale));
}
/**
* Returns the provider's localized object for the specified
* locale.
--- 204,246 ----
* merged array of all the locales that are provided by each
* provider, including the JRE.
*
* @return an array of the available locales
*/
! public Locale[] getAvailableLocales() {
! Set<Locale> locList = getAvailableLocaleList();
! Locale[] tmp = new Locale[locList.size()];
! locList.toArray(tmp);
return tmp;
}
! private synchronized Set<Locale> getAvailableLocaleList() {
! if (availableLocales == null) {
! availableLocales = new HashSet<>();
! for (LocaleServiceProvider lsp : providers.values()) {
Locale[] locales = lsp.getAvailableLocales();
for (Locale locale: locales) {
! availableLocales.add(getLookupLocale(locale));
}
}
! // Remove Locale.ROOT for the compatibility.
! availableLocales.remove(Locale.ROOT);
}
! return availableLocales;
}
/**
! * Returns whether any provider for this locale sensitive
! * service is available or not, excluding JRE's one.
*
! * @return true if any provider (other than JRE) is available
*/
! boolean hasProviders() {
! return providers.size() != 1 ||
! providers.get(LocaleProviderAdapter.Type.JRE) == null;
}
/**
* Returns the provider's localized object for the specified
* locale.
*** 295,480 ****
* is called to obtain the provider's instance.
* @param locale the given locale that is used as the starting one
* @param params provider specific parameters
* @return provider's instance, or null.
*/
! public <P, S> S getLocalizedObject(LocalizedObjectGetter<P, S> getter,
Locale locale,
Object... params) {
! return getLocalizedObjectImpl(getter, locale, true, null, null, null, params);
}
/**
* Returns the provider's localized name for the specified
* locale.
*
* @param getter an object on which getObject() method
* is called to obtain the provider's instance.
* @param locale the given locale that is used as the starting one
! * @param bundle JRE resource bundle that contains
! * the localized names, or null for localized objects.
! * @param key the key string if bundle is supplied, otherwise null.
* @param params provider specific parameters
* @return provider's instance, or null.
*/
! public <P, S> S getLocalizedObject(LocalizedObjectGetter<P, S> getter,
Locale locale,
- OpenListResourceBundle bundle,
String key,
Object... params) {
! return getLocalizedObjectImpl(getter, locale, false, null, bundle, key, params);
}
! /**
! * Returns the provider's localized name for the specified
! * locale.
! *
! * @param getter an object on which getObject() method
! * is called to obtain the provider's instance.
! * @param locale the given locale that is used as the starting one
! * @param bundleKey JRE specific bundle key. e.g., "USD" is for currency
! symbol and "usd" is for currency display name in the JRE bundle.
! * @param bundle JRE resource bundle that contains
! * the localized names, or null for localized objects.
! * @param key the key string if bundle is supplied, otherwise null.
! * @param params provider specific parameters
! * @return provider's instance, or null.
! */
! public <P, S> S getLocalizedObject(LocalizedObjectGetter<P, S> getter,
Locale locale,
! String bundleKey,
! OpenListResourceBundle bundle,
String key,
Object... params) {
! return getLocalizedObjectImpl(getter, locale, false, bundleKey, bundle, key, params);
}
! private <P, S> S getLocalizedObjectImpl(LocalizedObjectGetter<P, S> getter,
! Locale locale,
! boolean isObjectProvider,
! String bundleKey,
! OpenListResourceBundle bundle,
! String key,
! Object... params) {
! if (hasProviders()) {
! if (bundleKey == null) {
! bundleKey = key;
}
! Locale bundleLocale = (bundle != null ? bundle.getLocale() : null);
List<Locale> lookupLocales = getLookupLocales(locale);
- S providersObj = null;
! // check whether a provider has an implementation that's closer
! // to the requested locale than the bundle we've found (for
! // localized names), or Java runtime's supported locale
! // (for localized objects)
! Set<Locale> provLoc = getProviderLocales();
! for (int i = 0; i < lookupLocales.size(); i++) {
! Locale current = lookupLocales.get(i);
! if (bundleLocale != null) {
! if (current.equals(bundleLocale)) {
! break;
! }
! } else {
! if (isJRESupported(current)) {
! break;
! }
! }
! if (provLoc.contains(current)) {
! // It is safe to assume that findProvider() returns the instance of type P.
! @SuppressWarnings("unchecked")
! P lsp = (P)findProvider(current);
! if (lsp != null) {
! providersObj = getter.getObject(lsp, locale, key, params);
if (providersObj != null) {
return providersObj;
} else if (isObjectProvider) {
! config(
! "A locale sensitive service provider returned null for a localized objects, which should not happen. provider: " + lsp + " locale: " + locale);
}
}
}
}
- // look up the JRE bundle and its parent chain. Only
- // providers for localized names are checked hereafter.
- while (bundle != null) {
- bundleLocale = bundle.getLocale();
-
- if (bundle.handleGetKeys().contains(bundleKey)) {
- // JRE has it.
- return null;
- } else {
- // It is safe to assume that findProvider() returns the instance of type P.
- @SuppressWarnings("unchecked")
- P lsp = (P)findProvider(bundleLocale);
- if (lsp != null) {
- providersObj = getter.getObject(lsp, locale, key, params);
- if (providersObj != null) {
- return providersObj;
- }
- }
- }
-
- // try parent bundle
- bundle = bundle.getParent();
- }
- }
-
// not found.
return null;
}
/**
! * Returns a locale service provider instance that supports
* the specified locale.
*
* @param locale the given locale
! * @return the provider, or null if there is
! * no provider available.
*/
! private LocaleServiceProvider findProvider(Locale locale) {
! if (!hasProviders()) {
! return null;
}
- if (providersCache.containsKey(locale)) {
- LocaleServiceProvider provider = providersCache.get(locale);
- if (provider != NullProvider.INSTANCE) {
- return provider;
}
- } else {
- for (LocaleServiceProvider lsp : providers) {
- Locale[] locales = lsp.getAvailableLocales();
- for (Locale available: locales) {
- // normalize
- available = getLookupLocale(available);
- if (locale.equals(available)) {
- LocaleServiceProvider providerInCache =
- providersCache.put(locale, lsp);
- return (providerInCache != null ?
- providerInCache :
- lsp);
}
}
}
! providersCache.put(locale, NullProvider.INSTANCE);
}
- return null;
}
/**
* Returns a list of candidate locales for service look up.
* @param locale the input locale
! * @return the list of candiate locales for the given locale
*/
private static List<Locale> getLookupLocales(Locale locale) {
// Note: We currently use the default implementation of
// ResourceBundle.Control.getCandidateLocales. The result
// returned by getCandidateLocales are already normalized
// (no extensions) for service look up.
! List<Locale> lookupLocales = new Control(){}.getCandidateLocales("", locale);
return lookupLocales;
}
/**
* Returns an instance of Locale used for service look up.
--- 249,370 ----
* is called to obtain the provider's instance.
* @param locale the given locale that is used as the starting one
* @param params provider specific parameters
* @return provider's instance, or null.
*/
! public <P extends LocaleServiceProvider, S> S getLocalizedObject(LocalizedObjectGetter<P, S> getter,
Locale locale,
Object... params) {
! return getLocalizedObjectImpl(getter, locale, true, null, params);
}
/**
* Returns the provider's localized name for the specified
* locale.
*
* @param getter an object on which getObject() method
* is called to obtain the provider's instance.
* @param locale the given locale that is used as the starting one
! * @param key the key string for name providers
* @param params provider specific parameters
* @return provider's instance, or null.
*/
! public <P extends LocaleServiceProvider, S> S getLocalizedObject(LocalizedObjectGetter<P, S> getter,
Locale locale,
String key,
Object... params) {
! return getLocalizedObjectImpl(getter, locale, false, key, params);
}
! @SuppressWarnings("unchecked")
! private <P extends LocaleServiceProvider, S> S getLocalizedObjectImpl(LocalizedObjectGetter<P, S> getter,
Locale locale,
! boolean isObjectProvider,
String key,
Object... params) {
! if (locale == null) {
! throw new NullPointerException();
}
! // 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);
}
!
List<Locale> lookupLocales = getLookupLocales(locale);
! Set<Locale> available = getAvailableLocaleList();
! for (Locale current : lookupLocales) {
! if (available.contains(current)) {
! S providersObj;
!
! for (LocaleProviderAdapter.Type type: findProviders(current)) {
! LocaleServiceProvider lsp = providers.get(type);
! providersObj = getter.getObject((P)lsp, current, key, params);
if (providersObj != null) {
return providersObj;
} else if (isObjectProvider) {
! config(LocaleServiceProviderPool.class,
! "A locale sensitive service provider returned null for a localized objects, which should not happen. provider: "
! + lsp + " locale: " + locale);
}
}
}
}
// not found.
return null;
}
/**
! * Returns the list of locale service provider instances that support
* the specified locale.
*
* @param locale the given locale
! * @return the list of locale data adapter types
*/
! private List<LocaleProviderAdapter.Type> findProviders(Locale locale) {
! List<LocaleProviderAdapter.Type> providersList = providersCache.get(locale);
! if (providersList == null) {
! for (LocaleProviderAdapter.Type type : LocaleProviderAdapter.getAdapterPreference()) {
! LocaleServiceProvider lsp = providers.get(type);
! if (lsp != null) {
! if (lsp.isSupportedLocale(locale)) {
! if (providersList == null) {
! providersList = new ArrayList<>(2);
}
+ providersList.add(type);
}
}
}
+ if (providersList == null) {
+ providersList = NULL_LIST;
}
! List<LocaleProviderAdapter.Type> val = providersCache.putIfAbsent(locale, providersList);
! if (val != null) {
! providersList = val;
}
}
+ return providersList;
+ }
/**
* Returns a list of candidate locales for service look up.
* @param locale the input locale
! * @return the list of candidate locales for the given locale
*/
private static List<Locale> getLookupLocales(Locale locale) {
// Note: We currently use the default implementation of
// ResourceBundle.Control.getCandidateLocales. The result
// returned by getCandidateLocales are already normalized
// (no extensions) for service look up.
! List<Locale> lookupLocales = Control.getNoFallbackControl(Control.FORMAT_DEFAULT)
! .getCandidateLocales("", locale);
return lookupLocales;
}
/**
* Returns an instance of Locale used for service look up.
*** 482,497 ****
* and th_TH_TH
*
* @param locale the locale
* @return the locale used for service look up
*/
! private static Locale getLookupLocale(Locale locale) {
Locale lookupLocale = locale;
! Set<Character> extensions = locale.getExtensionKeys();
! if (!extensions.isEmpty()
! && !locale.equals(locale_ja_JP_JP)
! && !locale.equals(locale_th_TH_TH)) {
// remove extensions
Builder locbld = new Builder();
try {
locbld.setLocale(locale);
locbld.clearExtensions();
--- 372,386 ----
* and th_TH_TH
*
* @param locale the locale
* @return the locale used for service look up
*/
! static Locale getLookupLocale(Locale locale) {
Locale lookupLocale = locale;
! if (locale.hasExtensions()
! && !locale.equals(JRELocaleConstants.JA_JP_JP)
! && !locale.equals(JRELocaleConstants.TH_TH_TH)) {
// remove extensions
Builder locbld = new Builder();
try {
locbld.setLocale(locale);
locbld.clearExtensions();
*** 499,534 ****
} catch (IllformedLocaleException e) {
// A Locale with non-empty extensions
// should have well-formed fields except
// for ja_JP_JP and th_TH_TH. Therefore,
// it should never enter in this catch clause.
! config("A locale(" + locale + ") has non-empty extensions, but has illformed fields.");
// Fallback - script field will be lost.
lookupLocale = new Locale(locale.getLanguage(), locale.getCountry(), locale.getVariant());
}
}
return lookupLocale;
}
/**
! * A dummy locale service provider that indicates there is no
* provider available
*/
! private static class NullProvider extends LocaleServiceProvider {
! private static final NullProvider INSTANCE = new NullProvider();
- public Locale[] getAvailableLocales() {
- throw new RuntimeException("Should not get called.");
- }
- }
-
/**
! * An interface to get a localized object for each locale sensitve
* service class.
*/
! public interface LocalizedObjectGetter<P, S> {
/**
* Returns an object from the provider
*
* @param lsp the provider
* @param locale the locale
--- 388,419 ----
} catch (IllformedLocaleException e) {
// A Locale with non-empty extensions
// should have well-formed fields except
// for ja_JP_JP and th_TH_TH. Therefore,
// it should never enter in this catch clause.
! config(LocaleServiceProviderPool.class,
! "A locale(" + locale + ") has non-empty extensions, but has illformed fields.");
// Fallback - script field will be lost.
lookupLocale = new Locale(locale.getLanguage(), locale.getCountry(), locale.getVariant());
}
}
return lookupLocale;
}
/**
! * A dummy locale service provider list that indicates there is no
* provider available
*/
! private static List<LocaleProviderAdapter.Type> NULL_LIST =
! Collections.emptyList();
/**
! * An interface to get a localized object for each locale sensitive
* service class.
*/
! public interface LocalizedObjectGetter<P extends LocaleServiceProvider, S> {
/**
* Returns an object from the provider
*
* @param lsp the provider
* @param locale the locale