|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.util.locale.provider; |
|
|
|
import java.security.AccessController; |
|
import java.text.spi.BreakIteratorProvider; |
|
import java.text.spi.CollatorProvider; |
|
import java.text.spi.DateFormatProvider; |
|
import java.text.spi.DateFormatSymbolsProvider; |
|
import java.text.spi.DecimalFormatSymbolsProvider; |
|
import java.text.spi.NumberFormatProvider; |
|
import java.util.ArrayList; |
|
import java.util.Collections; |
|
import java.util.List; |
|
import java.util.Locale; |
|
import java.util.ResourceBundle; |
|
import java.util.Set; |
|
import java.util.concurrent.ConcurrentHashMap; |
|
import java.util.concurrent.ConcurrentMap; |
|
import java.util.spi.CalendarDataProvider; |
|
import java.util.spi.CalendarNameProvider; |
|
import java.util.spi.CurrencyNameProvider; |
|
import java.util.spi.LocaleNameProvider; |
|
import java.util.spi.LocaleServiceProvider; |
|
import java.util.spi.TimeZoneNameProvider; |
|
import sun.util.cldr.CLDRLocaleProviderAdapter; |
|
import sun.util.spi.CalendarProvider; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract class LocaleProviderAdapter { |
|
|
|
|
|
*/ |
|
public static enum Type { |
|
JRE("sun.util.resources", "sun.text.resources"), |
|
CLDR("sun.util.resources.cldr", "sun.text.resources.cldr"), |
|
SPI, |
|
HOST, |
|
FALLBACK("sun.util.resources", "sun.text.resources"); |
|
|
|
private final String UTIL_RESOURCES_PACKAGE; |
|
private final String TEXT_RESOURCES_PACKAGE; |
|
|
|
private Type() { |
|
this(null, null); |
|
} |
|
|
|
private Type(String util, String text) { |
|
UTIL_RESOURCES_PACKAGE = util; |
|
TEXT_RESOURCES_PACKAGE = text; |
|
} |
|
|
|
public String getUtilResourcesPackage() { |
|
return UTIL_RESOURCES_PACKAGE; |
|
} |
|
|
|
public String getTextResourcesPackage() { |
|
return TEXT_RESOURCES_PACKAGE; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private static final List<Type> adapterPreference; |
|
|
|
|
|
|
|
*/ |
|
private static LocaleProviderAdapter jreLocaleProviderAdapter = new JRELocaleProviderAdapter(); |
|
|
|
|
|
|
|
*/ |
|
private static LocaleProviderAdapter spiLocaleProviderAdapter = new SPILocaleProviderAdapter(); |
|
|
|
|
|
|
|
*/ |
|
private static LocaleProviderAdapter cldrLocaleProviderAdapter = null; |
|
|
|
|
|
|
|
*/ |
|
private static LocaleProviderAdapter hostLocaleProviderAdapter = null; |
|
|
|
|
|
|
|
|
|
*/ |
|
private static LocaleProviderAdapter fallbackLocaleProviderAdapter = null; |
|
|
|
|
|
|
|
|
|
*/ |
|
static LocaleProviderAdapter.Type defaultLocaleProviderAdapter = null; |
|
|
|
|
|
|
|
*/ |
|
private static ConcurrentMap<Class<? extends LocaleServiceProvider>, ConcurrentMap<Locale, LocaleProviderAdapter>> |
|
adapterCache = new ConcurrentHashMap<>(); |
|
|
|
static { |
|
String order = AccessController.doPrivileged( |
|
new sun.security.action.GetPropertyAction("java.locale.providers")); |
|
List<Type> typeList = new ArrayList<>(); |
|
|
|
|
|
if (order != null && order.length() != 0) { |
|
String[] types = order.split(","); |
|
for (String type : types) { |
|
try { |
|
Type aType = Type.valueOf(type.trim().toUpperCase(Locale.ROOT)); |
|
|
|
|
|
switch (aType) { |
|
case CLDR: |
|
if (cldrLocaleProviderAdapter == null) { |
|
cldrLocaleProviderAdapter = new CLDRLocaleProviderAdapter(); |
|
} |
|
break; |
|
case HOST: |
|
if (hostLocaleProviderAdapter == null) { |
|
hostLocaleProviderAdapter = new HostLocaleProviderAdapter(); |
|
} |
|
break; |
|
} |
|
if (!typeList.contains(aType)) { |
|
typeList.add(aType); |
|
} |
|
} catch (IllegalArgumentException | UnsupportedOperationException e) { |
|
// could be caused by the user specifying wrong |
|
|
|
LocaleServiceProviderPool.config(LocaleProviderAdapter.class, e.toString()); |
|
} |
|
} |
|
} |
|
|
|
if (!typeList.isEmpty()) { |
|
if (!typeList.contains(Type.JRE)) { |
|
|
|
fallbackLocaleProviderAdapter = new FallbackLocaleProviderAdapter(); |
|
typeList.add(Type.FALLBACK); |
|
defaultLocaleProviderAdapter = Type.FALLBACK; |
|
} else { |
|
defaultLocaleProviderAdapter = Type.JRE; |
|
} |
|
} else { |
|
|
|
typeList.add(Type.JRE); |
|
typeList.add(Type.SPI); |
|
defaultLocaleProviderAdapter = Type.JRE; |
|
} |
|
|
|
adapterPreference = Collections.unmodifiableList(typeList); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static LocaleProviderAdapter forType(Type type) { |
|
switch (type) { |
|
case JRE: |
|
return jreLocaleProviderAdapter; |
|
case CLDR: |
|
return cldrLocaleProviderAdapter; |
|
case SPI: |
|
return spiLocaleProviderAdapter; |
|
case HOST: |
|
return hostLocaleProviderAdapter; |
|
case FALLBACK: |
|
return fallbackLocaleProviderAdapter; |
|
default: |
|
throw new InternalError("unknown locale data adapter type"); |
|
} |
|
} |
|
|
|
public static LocaleProviderAdapter forJRE() { |
|
return jreLocaleProviderAdapter; |
|
} |
|
|
|
public static LocaleProviderAdapter getResourceBundleBased() { |
|
for (Type type : getAdapterPreference()) { |
|
if (type == Type.JRE || type == Type.CLDR || type == Type.FALLBACK) { |
|
return forType(type); |
|
} |
|
} |
|
|
|
throw new InternalError(); |
|
} |
|
|
|
|
|
*/ |
|
public static List<Type> getAdapterPreference() { |
|
return adapterPreference; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static LocaleProviderAdapter getAdapter(Class<? extends LocaleServiceProvider> providerClass, |
|
Locale locale) { |
|
LocaleProviderAdapter adapter; |
|
|
|
|
|
ConcurrentMap<Locale, LocaleProviderAdapter> adapterMap = adapterCache.get(providerClass); |
|
if (adapterMap != null) { |
|
if ((adapter = adapterMap.get(locale)) != null) { |
|
return adapter; |
|
} |
|
} else { |
|
adapterMap = new ConcurrentHashMap<>(); |
|
adapterCache.putIfAbsent(providerClass, adapterMap); |
|
} |
|
|
|
|
|
adapter = findAdapter(providerClass, locale); |
|
if (adapter != null) { |
|
adapterMap.putIfAbsent(locale, adapter); |
|
return adapter; |
|
} |
|
|
|
|
|
List<Locale> lookupLocales = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT) |
|
.getCandidateLocales("", locale); |
|
for (Locale loc : lookupLocales) { |
|
if (loc.equals(locale)) { |
|
|
|
continue; |
|
} |
|
adapter = findAdapter(providerClass, loc); |
|
if (adapter != null) { |
|
adapterMap.putIfAbsent(locale, adapter); |
|
return adapter; |
|
} |
|
} |
|
|
|
|
|
adapterMap.putIfAbsent(locale, fallbackLocaleProviderAdapter); |
|
return fallbackLocaleProviderAdapter; |
|
} |
|
|
|
private static LocaleProviderAdapter findAdapter(Class<? extends LocaleServiceProvider> providerClass, |
|
Locale locale) { |
|
for (Type type : getAdapterPreference()) { |
|
LocaleProviderAdapter adapter = forType(type); |
|
LocaleServiceProvider provider = adapter.getLocaleServiceProvider(providerClass); |
|
if (provider != null) { |
|
if (provider.isSupportedLocale(locale)) { |
|
return adapter; |
|
} |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static boolean isSupportedLocale(Locale locale, LocaleProviderAdapter.Type type, Set<String> langtags) { |
|
assert type == Type.JRE || type == Type.CLDR || type == Type.FALLBACK; |
|
if (Locale.ROOT.equals(locale)) { |
|
return true; |
|
} |
|
|
|
if (type == Type.FALLBACK) { |
|
|
|
return false; |
|
} |
|
|
|
locale = locale.stripExtensions(); |
|
if (langtags.contains(locale.toLanguageTag())) { |
|
return true; |
|
} |
|
if (type == Type.JRE) { |
|
String oldname = locale.toString().replace('_', '-'); |
|
return langtags.contains(oldname) || |
|
"ja-JP-JP".equals(oldname) || |
|
"th-TH-TH".equals(oldname) || |
|
"no-NO-NY".equals(oldname); |
|
} |
|
return false; |
|
} |
|
|
|
public static Locale[] toLocaleArray(Set<String> tags) { |
|
Locale[] locs = new Locale[tags.size() + 1]; |
|
int index = 0; |
|
locs[index++] = Locale.ROOT; |
|
for (String tag : tags) { |
|
switch (tag) { |
|
case "ja-JP-JP": |
|
locs[index++] = JRELocaleConstants.JA_JP_JP; |
|
break; |
|
case "th-TH-TH": |
|
locs[index++] = JRELocaleConstants.TH_TH_TH; |
|
break; |
|
default: |
|
locs[index++] = Locale.forLanguageTag(tag); |
|
break; |
|
} |
|
} |
|
return locs; |
|
} |
|
|
|
|
|
|
|
*/ |
|
public abstract LocaleProviderAdapter.Type getAdapterType(); |
|
|
|
|
|
|
|
*/ |
|
public abstract <P extends LocaleServiceProvider> P getLocaleServiceProvider(Class<P> c); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract BreakIteratorProvider getBreakIteratorProvider(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract CollatorProvider getCollatorProvider(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract DateFormatProvider getDateFormatProvider(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract DateFormatSymbolsProvider getDateFormatSymbolsProvider(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract NumberFormatProvider getNumberFormatProvider(); |
|
|
|
/* |
|
* Getter methods for java.util.spi.* providers |
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract CurrencyNameProvider getCurrencyNameProvider(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract LocaleNameProvider getLocaleNameProvider(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract TimeZoneNameProvider getTimeZoneNameProvider(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract CalendarDataProvider getCalendarDataProvider(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract CalendarNameProvider getCalendarNameProvider(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract CalendarProvider getCalendarProvider(); |
|
|
|
public abstract LocaleResources getLocaleResources(Locale locale); |
|
|
|
public abstract Locale[] getAvailableLocales(); |
|
} |