7162007: Clean up i18n related caches
Reviewed-by: okutsu, ohair
This commit is contained in:
parent
e912773451
commit
9fa2377054
@ -227,6 +227,7 @@ JAVA_JAVA_java = \
|
||||
sun/util/locale/provider/LocaleResources.java \
|
||||
sun/util/locale/provider/NumberFormatProviderImpl.java \
|
||||
sun/util/locale/provider/RuleBasedBreakIterator.java \
|
||||
sun/util/locale/provider/ResourceBundleBasedAdapter.java \
|
||||
sun/util/locale/provider/SPILocaleProviderAdapter.java \
|
||||
sun/util/locale/provider/TimeZoneNameProviderImpl.java \
|
||||
sun/util/locale/provider/TimeZoneNameUtility.java \
|
||||
|
@ -52,6 +52,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleServiceProviderPool;
|
||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
import sun.util.locale.provider.TimeZoneNameUtility;
|
||||
|
||||
/**
|
||||
@ -680,13 +681,10 @@ public class DateFormatSymbols implements Serializable, Cloneable {
|
||||
// Initialize the fields from the ResourceBundle for locale.
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
|
||||
// Avoid any potential recursions
|
||||
switch (adapter.getAdapterType()) {
|
||||
case HOST:
|
||||
case SPI:
|
||||
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
|
||||
adapter = LocaleProviderAdapter.getResourceBundleBased();
|
||||
break;
|
||||
}
|
||||
ResourceBundle resource = adapter.getLocaleData().getDateFormatData(locale);
|
||||
ResourceBundle resource = ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(locale);
|
||||
|
||||
// JRE and CLDR use different keys
|
||||
// JRE: Eras, short.Eras and narrow.Eras
|
||||
|
@ -54,6 +54,7 @@ import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
|
||||
/**
|
||||
* <code>DecimalFormat</code> is a concrete subclass of
|
||||
@ -394,28 +395,17 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @see java.text.NumberFormat#getPercentInstance
|
||||
*/
|
||||
public DecimalFormat() {
|
||||
// Get the pattern for the default locale.
|
||||
Locale def = Locale.getDefault(Locale.Category.FORMAT);
|
||||
// try to get the pattern from the cache
|
||||
String pattern = cachedLocaleData.get(def);
|
||||
if (pattern == null) { /* cache miss */
|
||||
// Get the pattern for the default locale.
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, def);
|
||||
switch (adapter.getAdapterType()) {
|
||||
case HOST:
|
||||
case SPI:
|
||||
adapter = LocaleProviderAdapter.getResourceBundleBased();
|
||||
break;
|
||||
}
|
||||
ResourceBundle rb = adapter.getLocaleData().getNumberFormatData(def);
|
||||
String[] all = rb.getStringArray("NumberPatterns");
|
||||
pattern = all[0];
|
||||
/* update cache */
|
||||
cachedLocaleData.putIfAbsent(def, pattern);
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(NumberFormatProvider.class, def);
|
||||
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
|
||||
adapter = LocaleProviderAdapter.getResourceBundleBased();
|
||||
}
|
||||
String[] all = adapter.getLocaleResources(def).getNumberPatterns();
|
||||
|
||||
// Always applyPattern after the symbols are set
|
||||
this.symbols = DecimalFormatSymbols.getInstance(def);
|
||||
applyPattern(pattern, false);
|
||||
applyPattern(all[0], false);
|
||||
}
|
||||
|
||||
|
||||
@ -4154,10 +4144,4 @@ public class DecimalFormat extends NumberFormat {
|
||||
|
||||
// Proclaim JDK 1.1 serial compatibility.
|
||||
static final long serialVersionUID = 864413376551465018L;
|
||||
|
||||
/**
|
||||
* Cache to hold the NumberPattern of a Locale.
|
||||
*/
|
||||
private static final ConcurrentMap<Locale, String> cachedLocaleData
|
||||
= new ConcurrentHashMap<>(3);
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleServiceProviderPool;
|
||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
|
||||
/**
|
||||
* This class represents the set of symbols (such as the decimal separator,
|
||||
@ -542,48 +543,13 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
|
||||
private void initialize( Locale locale ) {
|
||||
this.locale = locale;
|
||||
|
||||
// get resource bundle data - try the cache first
|
||||
boolean needCacheUpdate = false;
|
||||
Object[] data = cachedLocaleData.get(locale);
|
||||
if (data == null) { /* cache miss */
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, locale);
|
||||
// Avoid potential recursions
|
||||
switch (adapter.getAdapterType()) {
|
||||
case HOST:
|
||||
case SPI:
|
||||
adapter = LocaleProviderAdapter.getResourceBundleBased();
|
||||
break;
|
||||
}
|
||||
ResourceBundle rb = adapter.getLocaleData().getNumberFormatData(locale);
|
||||
data = new Object[3];
|
||||
|
||||
// NumberElements look up. First, try the Unicode extension
|
||||
String numElemKey;
|
||||
String numberType = locale.getUnicodeLocaleType("nu");
|
||||
if (numberType != null) {
|
||||
numElemKey = numberType + ".NumberElements";
|
||||
if (rb.containsKey(numElemKey)) {
|
||||
data[0] = rb.getStringArray(numElemKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Next, try DefaultNumberingSystem value
|
||||
if (data[0] == null && rb.containsKey("DefaultNumberingSystem")) {
|
||||
numElemKey = rb.getString("DefaultNumberingSystem") + ".NumberElements";
|
||||
if (rb.containsKey(numElemKey)) {
|
||||
data[0] = rb.getStringArray(numElemKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Last resort. No need to check the availability.
|
||||
// Just let it throw MissingResourceException when needed.
|
||||
if (data[0] == null) {
|
||||
data[0] = rb.getStringArray("NumberElements");
|
||||
}
|
||||
|
||||
needCacheUpdate = true;
|
||||
// get resource bundle data
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, locale);
|
||||
// Avoid potential recursions
|
||||
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
|
||||
adapter = LocaleProviderAdapter.getResourceBundleBased();
|
||||
}
|
||||
|
||||
Object[] data = adapter.getLocaleResources(locale).getDecimalFormatSymbolsData();
|
||||
String[] numberElements = (String[]) data[0];
|
||||
|
||||
decimalSeparator = numberElements[0].charAt(0);
|
||||
@ -618,7 +584,6 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
|
||||
currencySymbol = currency.getSymbol(locale);
|
||||
data[1] = intlCurrencySymbol;
|
||||
data[2] = currencySymbol;
|
||||
needCacheUpdate = true;
|
||||
}
|
||||
} else {
|
||||
// default values
|
||||
@ -633,10 +598,6 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
|
||||
// standard decimal separator for all locales that we support.
|
||||
// If that changes, add a new entry to NumberElements.
|
||||
monetarySeparator = decimalSeparator;
|
||||
|
||||
if (needCacheUpdate) {
|
||||
cachedLocaleData.putIfAbsent(locale, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -850,11 +811,4 @@ public class DecimalFormatSymbols implements Cloneable, Serializable {
|
||||
* @since JDK 1.1.6
|
||||
*/
|
||||
private int serialVersionOnStream = currentSerialVersion;
|
||||
|
||||
/**
|
||||
* cache to hold the NumberElements and the Currency
|
||||
* of a Locale.
|
||||
*/
|
||||
private static final ConcurrentMap<Locale, Object[]> cachedLocaleData
|
||||
= new ConcurrentHashMap<>(3);
|
||||
}
|
||||
|
@ -56,7 +56,6 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleServiceProviderPool;
|
||||
import sun.util.resources.LocaleData;
|
||||
|
||||
/**
|
||||
* <code>NumberFormat</code> is the abstract base class for all number
|
||||
|
@ -50,7 +50,6 @@ import java.text.MessageFormat;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.util.locale.provider.LocaleServiceProviderPool;
|
||||
import sun.util.locale.BaseLocale;
|
||||
import sun.util.locale.InternalLocaleBuilder;
|
||||
import sun.util.locale.LanguageTag;
|
||||
@ -61,7 +60,9 @@ import sun.util.locale.LocaleSyntaxException;
|
||||
import sun.util.locale.LocaleUtils;
|
||||
import sun.util.locale.ParseStatus;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.resources.OpenListResourceBundle;
|
||||
import sun.util.locale.provider.LocaleResources;
|
||||
import sun.util.locale.provider.LocaleServiceProviderPool;
|
||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
|
||||
/**
|
||||
* A <code>Locale</code> object represents a specific geographical, political,
|
||||
@ -1779,20 +1780,15 @@ public final class Locale implements Cloneable, Serializable {
|
||||
if (baseLocale.getVariant().length() == 0)
|
||||
return "";
|
||||
|
||||
OpenListResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getLocaleNames(inLocale);
|
||||
LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(inLocale);
|
||||
|
||||
String names[] = getDisplayVariantArray(bundle, inLocale);
|
||||
String names[] = getDisplayVariantArray(inLocale);
|
||||
|
||||
// Get the localized patterns for formatting a list, and use
|
||||
// them to format the list.
|
||||
String listPattern = null;
|
||||
String listCompositionPattern = null;
|
||||
try {
|
||||
listPattern = bundle.getString("ListPattern");
|
||||
listCompositionPattern = bundle.getString("ListCompositionPattern");
|
||||
} catch (MissingResourceException e) {
|
||||
}
|
||||
return formatList(names, listPattern, listCompositionPattern);
|
||||
return formatList(names,
|
||||
lr.getLocaleName("ListPattern"),
|
||||
lr.getLocaleName("ListCompositionPattern"));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1837,23 +1833,17 @@ public final class Locale implements Cloneable, Serializable {
|
||||
* @throws NullPointerException if <code>inLocale</code> is <code>null</code>
|
||||
*/
|
||||
public String getDisplayName(Locale inLocale) {
|
||||
OpenListResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getLocaleNames(inLocale);
|
||||
LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(inLocale);
|
||||
|
||||
String languageName = getDisplayLanguage(inLocale);
|
||||
String scriptName = getDisplayScript(inLocale);
|
||||
String countryName = getDisplayCountry(inLocale);
|
||||
String[] variantNames = getDisplayVariantArray(bundle, inLocale);
|
||||
String[] variantNames = getDisplayVariantArray(inLocale);
|
||||
|
||||
// Get the localized patterns for formatting a display name.
|
||||
String displayNamePattern = null;
|
||||
String listPattern = null;
|
||||
String listCompositionPattern = null;
|
||||
try {
|
||||
displayNamePattern = bundle.getString("DisplayNamePattern");
|
||||
listPattern = bundle.getString("ListPattern");
|
||||
listCompositionPattern = bundle.getString("ListCompositionPattern");
|
||||
} catch (MissingResourceException e) {
|
||||
}
|
||||
String displayNamePattern = lr.getLocaleName("DisplayNamePattern");
|
||||
String listPattern = lr.getLocaleName("ListPattern");
|
||||
String listCompositionPattern = lr.getLocaleName("ListCompositionPattern");
|
||||
|
||||
// The display name consists of a main name, followed by qualifiers.
|
||||
// Typically, the format is "MainName (Qualifier, Qualifier)" but this
|
||||
@ -2005,7 +1995,7 @@ public final class Locale implements Cloneable, Serializable {
|
||||
* @param bundle the ResourceBundle to use to get the display names
|
||||
* @return an array of display names, possible of zero length.
|
||||
*/
|
||||
private String[] getDisplayVariantArray(OpenListResourceBundle bundle, Locale inLocale) {
|
||||
private String[] getDisplayVariantArray(Locale inLocale) {
|
||||
// Split the variant name into tokens separated by '_'.
|
||||
StringTokenizer tokenizer = new StringTokenizer(baseLocale.getVariant(), "_");
|
||||
String[] names = new String[tokenizer.countTokens()];
|
||||
|
@ -430,32 +430,7 @@ abstract public class TimeZone implements Serializable, Cloneable {
|
||||
}
|
||||
|
||||
private static String[] getDisplayNames(String id, Locale locale) {
|
||||
Map<String, SoftReference<Map<Locale, String[]>>> displayNames = DisplayNames.CACHE;
|
||||
|
||||
SoftReference<Map<Locale, String[]>> ref = displayNames.get(id);
|
||||
if (ref != null) {
|
||||
Map<Locale, String[]> perLocale = ref.get();
|
||||
if (perLocale != null) {
|
||||
String[] names = perLocale.get(locale);
|
||||
if (names != null) {
|
||||
return names;
|
||||
}
|
||||
names = TimeZoneNameUtility.retrieveDisplayNames(id, locale);
|
||||
if (names != null) {
|
||||
perLocale.put(locale, names);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
}
|
||||
|
||||
String[] names = TimeZoneNameUtility.retrieveDisplayNames(id, locale);
|
||||
if (names != null) {
|
||||
Map<Locale, String[]> perLocale = new ConcurrentHashMap<>();
|
||||
perLocale.put(locale, names);
|
||||
ref = new SoftReference<>(perLocale);
|
||||
displayNames.put(id, ref);
|
||||
}
|
||||
return names;
|
||||
return TimeZoneNameUtility.retrieveDisplayNames(id, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,12 +47,13 @@ import java.util.ListResourceBundle;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
|
||||
public class CollationData_zh_HK extends ListResourceBundle {
|
||||
|
||||
// reparent to zh_TW for traditional Chinese collation sequence
|
||||
public CollationData_zh_HK() {
|
||||
ResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getCollationData(Locale.TAIWAN);
|
||||
ResourceBundle bundle = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getCollationData(Locale.TAIWAN);
|
||||
setParent(bundle);
|
||||
}
|
||||
|
||||
|
@ -44,12 +44,14 @@ import java.util.ListResourceBundle;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
|
||||
public class FormatData_zh_HK extends ListResourceBundle {
|
||||
|
||||
// reparent to zh_TW for traditional Chinese names
|
||||
public FormatData_zh_HK() {
|
||||
ResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getDateFormatData(Locale.TAIWAN);
|
||||
ResourceBundle bundle = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE())
|
||||
.getLocaleData().getDateFormatData(Locale.TAIWAN);
|
||||
setParent(bundle);
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,6 @@ import java.util.spi.CurrencyNameProvider;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
import sun.util.resources.LocaleData;
|
||||
|
||||
/**
|
||||
* An abstract parent class for the
|
||||
@ -146,11 +145,6 @@ public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocaleData getLocaleData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Locale[] availableLocales = null;
|
||||
|
||||
@Override
|
||||
|
@ -25,12 +25,12 @@
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.BreakIterator;
|
||||
import java.text.spi.BreakIteratorProvider;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Set;
|
||||
import sun.util.resources.LocaleData;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the {@link java.text.spi.BreakIteratorProvider
|
||||
@ -159,24 +159,22 @@ public class BreakIteratorProviderImpl extends BreakIteratorProvider
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
ResourceBundle bundle = LocaleData.getBundle(
|
||||
LocaleProviderAdapter.Type.JRE.getTextResourcesPackage() + ".BreakIteratorInfo", locale);
|
||||
String[] classNames = bundle.getStringArray("BreakIteratorClasses");
|
||||
|
||||
String dataFile = bundle.getString(dataName);
|
||||
LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(locale);
|
||||
String[] classNames = (String[]) lr.getBreakIteratorInfo("BreakIteratorClasses");
|
||||
String dataFile = (String) lr.getBreakIteratorInfo(dataName);
|
||||
|
||||
try {
|
||||
switch (classNames[type]) {
|
||||
case "RuleBasedBreakIterator":
|
||||
return new RuleBasedBreakIterator(dataFile);
|
||||
case "DictionaryBasedBreakIterator":
|
||||
String dictionaryFile = bundle.getString(dictionaryName);
|
||||
String dictionaryFile = (String) lr.getBreakIteratorInfo(dictionaryName);
|
||||
return new DictionaryBasedBreakIterator(dataFile, dictionaryFile);
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid break iterator class \"" +
|
||||
classNames[type] + "\"");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} catch (IOException | MissingResourceException | IllegalArgumentException e) {
|
||||
throw new InternalError(e.toString(), e);
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,7 @@
|
||||
*/
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Calendar;
|
||||
import static java.util.Calendar.*;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.spi.CalendarDataProvider;
|
||||
|
||||
@ -49,12 +46,14 @@ public class CalendarDataProviderImpl extends CalendarDataProvider implements Av
|
||||
|
||||
@Override
|
||||
public int getFirstDayOfWeek(Locale locale) {
|
||||
return getIntData(CalendarDataUtility.FIRST_DAY_OF_WEEK, locale);
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale)
|
||||
.getCalendarData(CalendarDataUtility.FIRST_DAY_OF_WEEK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimalDaysInFirstWeek(Locale locale) {
|
||||
return getIntData(CalendarDataUtility.MINIMAL_DAYS_IN_FIRST_WEEK, locale);
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale)
|
||||
.getCalendarData(CalendarDataUtility.MINIMAL_DAYS_IN_FIRST_WEEK);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -66,13 +65,4 @@ public class CalendarDataProviderImpl extends CalendarDataProvider implements Av
|
||||
public Set<String> getAvailableLanguageTags() {
|
||||
return langtags;
|
||||
}
|
||||
|
||||
private int getIntData(String key, Locale locale) {
|
||||
ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getCalendarData(locale);
|
||||
if (rb.containsKey(key)) {
|
||||
String firstday = rb.getString(key);
|
||||
return Integer.parseInt(firstday);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ import static java.util.Calendar.*;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.spi.CalendarNameProvider;
|
||||
@ -54,22 +53,19 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av
|
||||
String name = null;
|
||||
String key = getResourceKey(calendarType, field, style);
|
||||
if (key != null) {
|
||||
ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale);
|
||||
if (rb.containsKey(key)) {
|
||||
String[] strings = rb.getStringArray(key);
|
||||
if (strings.length > 0) {
|
||||
if (field == DAY_OF_WEEK || field == YEAR) {
|
||||
--value;
|
||||
}
|
||||
name = strings[value];
|
||||
// If name is empty in standalone, try its `format' style.
|
||||
if (name.length() == 0
|
||||
&& (style == SHORT_STANDALONE || style == LONG_STANDALONE
|
||||
|| style == NARROW_STANDALONE)) {
|
||||
name = getDisplayName(calendarType, field, value,
|
||||
getBaseStyle(style),
|
||||
locale);
|
||||
}
|
||||
String[] strings = LocaleProviderAdapter.forType(type).getLocaleResources(locale).getCalendarNames(key);
|
||||
if (strings != null && strings.length > 0) {
|
||||
if (field == DAY_OF_WEEK || field == YEAR) {
|
||||
--value;
|
||||
}
|
||||
name = strings[value];
|
||||
// If name is empty in standalone, try its `format' style.
|
||||
if (name.length() == 0
|
||||
&& (style == SHORT_STANDALONE || style == LONG_STANDALONE
|
||||
|| style == NARROW_STANDALONE)) {
|
||||
name = getDisplayName(calendarType, field, value,
|
||||
getBaseStyle(style),
|
||||
locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,9 +96,8 @@ public class CalendarNameProviderImpl extends CalendarNameProvider implements Av
|
||||
String key = getResourceKey(calendarType, field, style);
|
||||
Map<String, Integer> map = new TreeMap<>(LengthBasedComparator.INSTANCE);
|
||||
if (key != null) {
|
||||
ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale);
|
||||
if (rb.containsKey(key)) {
|
||||
String[] strings = rb.getStringArray(key);
|
||||
String[] strings = LocaleProviderAdapter.forType(type).getLocaleResources(locale).getCalendarNames(key);
|
||||
if (strings != null) {
|
||||
if (!hasDuplicates(strings)) {
|
||||
if (field == YEAR) {
|
||||
if (strings.length > 0) {
|
||||
|
@ -45,8 +45,6 @@ import java.text.ParseException;
|
||||
import java.text.RuleBasedCollator;
|
||||
import java.text.spi.CollatorProvider;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -102,14 +100,7 @@ public class CollatorProviderImpl extends CollatorProvider implements AvailableL
|
||||
|
||||
// Load the resource of the desired locale from resource
|
||||
// manager.
|
||||
String colString = "";
|
||||
try {
|
||||
ResourceBundle resource = LocaleProviderAdapter.forType(type).getLocaleData().getCollationData(locale);
|
||||
|
||||
colString = resource.getString("Rule");
|
||||
} catch (MissingResourceException e) {
|
||||
// Use default values
|
||||
}
|
||||
String colString = LocaleProviderAdapter.forType(type).getLocaleResources(locale).getCollationData();
|
||||
try
|
||||
{
|
||||
result = new RuleBasedCollator(CollationRules.DEFAULTRULES +
|
||||
|
@ -26,7 +26,6 @@
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.spi.CurrencyNameProvider;
|
||||
|
||||
@ -120,11 +119,6 @@ public class CurrencyNameProviderImpl extends CurrencyNameProvider
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
ResourceBundle bundle = LocaleProviderAdapter.forType(type).getLocaleData().getCurrencyNames(locale);
|
||||
if (bundle.containsKey(key)) {
|
||||
return bundle.getString(key);
|
||||
}
|
||||
|
||||
return null;
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale).getCurrencyName(key);
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ import sun.util.resources.LocaleData;
|
||||
* @author Naoto Sato
|
||||
* @author Masayoshi Okutsu
|
||||
*/
|
||||
public class JRELocaleProviderAdapter extends LocaleProviderAdapter {
|
||||
public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements ResourceBundleBasedAdapter {
|
||||
|
||||
private static final String LOCALE_DATA_JAR_NAME = "localedata.jar";
|
||||
|
||||
@ -296,6 +296,7 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter {
|
||||
return lr;
|
||||
}
|
||||
|
||||
// ResourceBundleBasedAdapter method implementation
|
||||
@Override
|
||||
public LocaleData getLocaleData() {
|
||||
if (localeData == null) {
|
||||
|
@ -26,7 +26,6 @@
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.spi.LocaleNameProvider;
|
||||
|
||||
@ -174,12 +173,7 @@ public class LocaleNameProviderImpl extends LocaleNameProvider implements Availa
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getLocaleNames(locale);
|
||||
if (rb.containsKey(key)) {
|
||||
return rb.getString(key);
|
||||
}
|
||||
|
||||
return null;
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale).getLocaleName(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,6 +37,8 @@ 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;
|
||||
@ -44,7 +46,6 @@ import java.util.spi.LocaleNameProvider;
|
||||
import java.util.spi.LocaleServiceProvider;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
import sun.util.cldr.CLDRLocaleProviderAdapter;
|
||||
import sun.util.resources.LocaleData;
|
||||
|
||||
/**
|
||||
* The LocaleProviderAdapter abstract class.
|
||||
@ -119,6 +120,12 @@ public abstract class LocaleProviderAdapter {
|
||||
*/
|
||||
private static LocaleProviderAdapter fallbackLocaleProviderAdapter = null;
|
||||
|
||||
/**
|
||||
* Adapter lookup cache.
|
||||
*/
|
||||
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"));
|
||||
@ -210,9 +217,23 @@ public abstract class LocaleProviderAdapter {
|
||||
*/
|
||||
public static LocaleProviderAdapter getAdapter(Class<? extends LocaleServiceProvider> providerClass,
|
||||
Locale locale) {
|
||||
LocaleProviderAdapter adapter;
|
||||
|
||||
// cache lookup
|
||||
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);
|
||||
}
|
||||
|
||||
// Fast look-up for the given locale
|
||||
LocaleProviderAdapter adapter = findAdapter(providerClass, locale);
|
||||
adapter = findAdapter(providerClass, locale);
|
||||
if (adapter != null) {
|
||||
adapterMap.putIfAbsent(locale, adapter);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@ -226,11 +247,13 @@ public abstract class LocaleProviderAdapter {
|
||||
}
|
||||
adapter = findAdapter(providerClass, loc);
|
||||
if (adapter != null) {
|
||||
adapterMap.putIfAbsent(locale, adapter);
|
||||
return adapter;
|
||||
}
|
||||
}
|
||||
|
||||
// returns the adapter for FALLBACK as the last resort
|
||||
adapterMap.putIfAbsent(locale, fallbackLocaleProviderAdapter);
|
||||
return fallbackLocaleProviderAdapter;
|
||||
}
|
||||
|
||||
@ -398,7 +421,5 @@ public abstract class LocaleProviderAdapter {
|
||||
|
||||
public abstract LocaleResources getLocaleResources(Locale locale);
|
||||
|
||||
public abstract LocaleData getLocaleData();
|
||||
|
||||
public abstract Locale[] getAvailableLocales();
|
||||
}
|
||||
|
@ -40,43 +40,295 @@
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import sun.util.calendar.ZoneInfo;
|
||||
import sun.util.resources.LocaleData;
|
||||
import sun.util.resources.OpenListResourceBundle;
|
||||
import sun.util.resources.TimeZoneNamesBundle;
|
||||
|
||||
/**
|
||||
* Central accessor to locale-dependent resources.
|
||||
* Central accessor to locale-dependent resources for JRE/CLDR provider adapters.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public class LocaleResources {
|
||||
|
||||
private final LocaleProviderAdapter adapter;
|
||||
private final Locale locale;
|
||||
private final LocaleData localeData;
|
||||
private final LocaleProviderAdapter.Type type;
|
||||
|
||||
// Resource cache
|
||||
private ConcurrentMap<String, Object> cache = new ConcurrentHashMap<>();
|
||||
private ConcurrentMap<String, ResourceReference> cache = new ConcurrentHashMap<>();
|
||||
private ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
|
||||
|
||||
// cache key prefixes
|
||||
private static final String BREAK_ITERATOR_INFO = "BII.";
|
||||
private static final String CALENDAR_DATA = "CALD.";
|
||||
private static final String COLLATION_DATA_CACHEKEY = "COLD";
|
||||
private static final String DECIMAL_FORMAT_SYMBOLS_DATA_CACHEKEY = "DFSD";
|
||||
private static final String CURRENCY_NAMES = "CN.";
|
||||
private static final String LOCALE_NAMES = "LN.";
|
||||
private static final String TIME_ZONE_NAMES = "TZN.";
|
||||
private static final String ZONE_IDS_CACHEKEY = "ZID";
|
||||
private static final String CALENDAR_NAMES = "CALN.";
|
||||
private static final String NUMBER_PATTERNS_CACHEKEY = "NP";
|
||||
private static final String DATE_TIME_PATTERN = "DTP.";
|
||||
|
||||
LocaleResources(LocaleProviderAdapter adapter, Locale locale) {
|
||||
this.adapter = adapter;
|
||||
// null singleton cache value
|
||||
private static final Object NULLOBJECT = new Object();
|
||||
|
||||
LocaleResources(ResourceBundleBasedAdapter adapter, Locale locale) {
|
||||
this.locale = locale;
|
||||
this.localeData = adapter.getLocaleData();
|
||||
type = ((LocaleProviderAdapter)adapter).getAdapterType();
|
||||
}
|
||||
|
||||
public TimeZoneNamesBundle getTimeZoneNames() {
|
||||
TimeZoneNamesBundle tznames = (TimeZoneNamesBundle) cache.get("TimeZoneNames");
|
||||
if (tznames == null) {
|
||||
tznames = adapter.getLocaleData().getTimeZoneNames(locale);
|
||||
TimeZoneNamesBundle tznb = (TimeZoneNamesBundle) cache.putIfAbsent("TimeZoneNames", tznames);
|
||||
if (tznb != null) {
|
||||
tznames = tznb;
|
||||
private void removeEmptyReferences() {
|
||||
Object ref;
|
||||
while ((ref = referenceQueue.poll()) != null) {
|
||||
cache.remove(((ResourceReference)ref).getCacheKey());
|
||||
}
|
||||
}
|
||||
|
||||
Object getBreakIteratorInfo(String key) {
|
||||
Object biInfo;
|
||||
String cacheKey = BREAK_ITERATOR_INFO + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
if (data == null || ((biInfo = data.get()) == null)) {
|
||||
biInfo = localeData.getBreakIteratorInfo(locale).getObject(key);
|
||||
cache.put(cacheKey, new ResourceReference(cacheKey, biInfo, referenceQueue));
|
||||
}
|
||||
|
||||
return biInfo;
|
||||
}
|
||||
|
||||
int getCalendarData(String key) {
|
||||
Integer caldata;
|
||||
String cacheKey = CALENDAR_DATA + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
if (data == null || ((caldata = (Integer) data.get()) == null)) {
|
||||
ResourceBundle rb = localeData.getCalendarData(locale);
|
||||
if (rb.containsKey(key)) {
|
||||
caldata = Integer.parseInt(rb.getString(key));
|
||||
} else {
|
||||
caldata = 0;
|
||||
}
|
||||
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, (Object) caldata, referenceQueue));
|
||||
}
|
||||
|
||||
return caldata;
|
||||
}
|
||||
|
||||
public String getCollationData() {
|
||||
String key = "Rule";
|
||||
String coldata = "";
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(COLLATION_DATA_CACHEKEY);
|
||||
if (data == null || ((coldata = (String) data.get()) == null)) {
|
||||
ResourceBundle rb = localeData.getCollationData(locale);
|
||||
if (rb.containsKey(key)) {
|
||||
coldata = rb.getString(key);
|
||||
}
|
||||
cache.put(COLLATION_DATA_CACHEKEY,
|
||||
new ResourceReference(COLLATION_DATA_CACHEKEY, (Object) coldata, referenceQueue));
|
||||
}
|
||||
|
||||
return coldata;
|
||||
}
|
||||
|
||||
public Object[] getDecimalFormatSymbolsData() {
|
||||
Object[] dfsdata;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(DECIMAL_FORMAT_SYMBOLS_DATA_CACHEKEY);
|
||||
if (data == null || ((dfsdata = (Object[]) data.get()) == null)) {
|
||||
// Note that only dfsdata[0] is prepared here in this method. Other
|
||||
// elements are provided by the caller, yet they are cached here.
|
||||
ResourceBundle rb = localeData.getNumberFormatData(locale);
|
||||
dfsdata = new Object[3];
|
||||
|
||||
// NumberElements look up. First, try the Unicode extension
|
||||
String numElemKey;
|
||||
String numberType = locale.getUnicodeLocaleType("nu");
|
||||
if (numberType != null) {
|
||||
numElemKey = numberType + ".NumberElements";
|
||||
if (rb.containsKey(numElemKey)) {
|
||||
dfsdata[0] = rb.getStringArray(numElemKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Next, try DefaultNumberingSystem value
|
||||
if (dfsdata[0] == null && rb.containsKey("DefaultNumberingSystem")) {
|
||||
numElemKey = rb.getString("DefaultNumberingSystem") + ".NumberElements";
|
||||
if (rb.containsKey(numElemKey)) {
|
||||
dfsdata[0] = rb.getStringArray(numElemKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Last resort. No need to check the availability.
|
||||
// Just let it throw MissingResourceException when needed.
|
||||
if (dfsdata[0] == null) {
|
||||
dfsdata[0] = rb.getStringArray("NumberElements");
|
||||
}
|
||||
|
||||
cache.put(DECIMAL_FORMAT_SYMBOLS_DATA_CACHEKEY,
|
||||
new ResourceReference(DECIMAL_FORMAT_SYMBOLS_DATA_CACHEKEY, (Object) dfsdata, referenceQueue));
|
||||
}
|
||||
|
||||
return dfsdata;
|
||||
}
|
||||
|
||||
public String getCurrencyName(String key) {
|
||||
Object currencyName = null;
|
||||
String cacheKey = CURRENCY_NAMES + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
|
||||
if (data != null && ((currencyName = data.get()) != null)) {
|
||||
if (currencyName.equals(NULLOBJECT)) {
|
||||
currencyName = null;
|
||||
}
|
||||
|
||||
return (String) currencyName;
|
||||
}
|
||||
|
||||
OpenListResourceBundle olrb = localeData.getCurrencyNames(locale);
|
||||
|
||||
if (olrb.containsKey(key)) {
|
||||
currencyName = olrb.getObject(key);
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, currencyName, referenceQueue));
|
||||
}
|
||||
|
||||
return (String) currencyName;
|
||||
}
|
||||
|
||||
public String getLocaleName(String key) {
|
||||
Object localeName = null;
|
||||
String cacheKey = LOCALE_NAMES + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
|
||||
if (data != null && ((localeName = data.get()) != null)) {
|
||||
if (localeName.equals(NULLOBJECT)) {
|
||||
localeName = null;
|
||||
}
|
||||
|
||||
return (String) localeName;
|
||||
}
|
||||
|
||||
OpenListResourceBundle olrb = localeData.getLocaleNames(locale);
|
||||
|
||||
if (olrb.containsKey(key)) {
|
||||
localeName = olrb.getObject(key);
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, localeName, referenceQueue));
|
||||
}
|
||||
|
||||
return (String) localeName;
|
||||
}
|
||||
|
||||
String[] getTimeZoneNames(String key, int size) {
|
||||
String[] names = null;
|
||||
String cacheKey = TIME_ZONE_NAMES + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
|
||||
if (data == null || ((names = (String[]) data.get()) == null)) {
|
||||
TimeZoneNamesBundle tznb = localeData.getTimeZoneNames(locale);
|
||||
if (tznb.containsKey(key)) {
|
||||
names = tznb.getStringArray(key, size);
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, (Object) names, referenceQueue));
|
||||
}
|
||||
}
|
||||
return tznames;
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> getZoneIDs() {
|
||||
Set<String> zoneIDs = null;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(ZONE_IDS_CACHEKEY);
|
||||
if (data == null || ((zoneIDs = (Set<String>) data.get()) == null)) {
|
||||
TimeZoneNamesBundle rb = localeData.getTimeZoneNames(locale);
|
||||
zoneIDs = rb.keySet();
|
||||
cache.put(ZONE_IDS_CACHEKEY,
|
||||
new ResourceReference(ZONE_IDS_CACHEKEY, (Object) zoneIDs, referenceQueue));
|
||||
}
|
||||
|
||||
return zoneIDs;
|
||||
}
|
||||
|
||||
// zoneStrings are cached separately in TimeZoneNameUtility.
|
||||
String[][] getZoneStrings() {
|
||||
TimeZoneNamesBundle rb = localeData.getTimeZoneNames(locale);
|
||||
Set<String> keyset = getZoneIDs();
|
||||
// Use a LinkedHashSet to preseve the order
|
||||
Set<String[]> value = new LinkedHashSet<>();
|
||||
for (String key : keyset) {
|
||||
value.add(rb.getStringArray(key));
|
||||
}
|
||||
|
||||
// Add aliases data for CLDR
|
||||
if (type == LocaleProviderAdapter.Type.CLDR) {
|
||||
// Note: TimeZoneNamesBundle creates a String[] on each getStringArray call.
|
||||
Map<String, String> aliases = ZoneInfo.getAliasTable();
|
||||
for (String alias : aliases.keySet()) {
|
||||
if (!keyset.contains(alias)) {
|
||||
String tzid = aliases.get(alias);
|
||||
if (keyset.contains(tzid)) {
|
||||
String[] val = rb.getStringArray(tzid);
|
||||
val[0] = alias;
|
||||
value.add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return value.toArray(new String[0][]);
|
||||
}
|
||||
|
||||
String[] getCalendarNames(String key) {
|
||||
String[] names = null;
|
||||
String cacheKey = CALENDAR_NAMES + key;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
|
||||
if (data == null || ((names = (String[]) data.get()) == null)) {
|
||||
ResourceBundle rb = localeData.getDateFormatData(locale);
|
||||
if (rb.containsKey(key)) {
|
||||
names = rb.getStringArray(key);
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, (Object) names, referenceQueue));
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
public String getDateTimePattern(int timeStyle, int dateStyle, Calendar cal) {
|
||||
@ -120,32 +372,54 @@ public class LocaleResources {
|
||||
}
|
||||
|
||||
public String[] getNumberPatterns() {
|
||||
/* try the cache first */
|
||||
String[] numberPatterns = (String[]) cache.get("NumberPatterns");
|
||||
if (numberPatterns == null) { /* cache miss */
|
||||
ResourceBundle resource = adapter.getLocaleData().getNumberFormatData(locale);
|
||||
String[] numberPatterns = null;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(NUMBER_PATTERNS_CACHEKEY);
|
||||
|
||||
if (data == null || ((numberPatterns = (String[]) data.get()) == null)) {
|
||||
ResourceBundle resource = localeData.getNumberFormatData(locale);
|
||||
numberPatterns = resource.getStringArray("NumberPatterns");
|
||||
/* update cache */
|
||||
cache.put("NumberPatterns", numberPatterns);
|
||||
cache.put(NUMBER_PATTERNS_CACHEKEY,
|
||||
new ResourceReference(NUMBER_PATTERNS_CACHEKEY, (Object) numberPatterns, referenceQueue));
|
||||
}
|
||||
|
||||
return numberPatterns;
|
||||
}
|
||||
|
||||
private String getDateTimePattern(String key, int styleIndex, String calendarType) {
|
||||
String resourceKey = "gregory".equals(calendarType) ? key : calendarType + "." + key;
|
||||
/* try the cache first */
|
||||
String[] patterns = (String[]) cache.get(resourceKey);
|
||||
if (patterns == null) { /* cache miss */
|
||||
ResourceBundle r = adapter.getLocaleData().getDateFormatData(locale);
|
||||
String cacheKey = DATE_TIME_PATTERN + resourceKey;
|
||||
String[] patterns = null;
|
||||
|
||||
removeEmptyReferences();
|
||||
ResourceReference data = cache.get(cacheKey);
|
||||
|
||||
if (data == null || ((patterns = (String[]) data.get()) == null)) {
|
||||
ResourceBundle r = localeData.getDateFormatData(locale);
|
||||
if (r.containsKey(resourceKey)) {
|
||||
patterns = r.getStringArray(resourceKey);
|
||||
} else {
|
||||
assert !resourceKey.equals(key);
|
||||
patterns = r.getStringArray(key);
|
||||
}
|
||||
/* update cache */
|
||||
cache.putIfAbsent(resourceKey, patterns);
|
||||
cache.put(cacheKey,
|
||||
new ResourceReference(cacheKey, (Object) patterns, referenceQueue));
|
||||
}
|
||||
|
||||
return patterns[styleIndex];
|
||||
}
|
||||
|
||||
private static class ResourceReference extends SoftReference<Object> {
|
||||
private final String cacheKey;
|
||||
|
||||
ResourceReference(String cacheKey, Object o, ReferenceQueue<Object> q) {
|
||||
super(o, q);
|
||||
this.cacheKey = cacheKey;
|
||||
}
|
||||
|
||||
String getCacheKey() {
|
||||
return cacheKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 sun.util.locale.provider;
|
||||
|
||||
import sun.util.resources.LocaleData;
|
||||
|
||||
/**
|
||||
* Accessor for LocaleData
|
||||
*
|
||||
* @author Naoto Sato
|
||||
*/
|
||||
public interface ResourceBundleBasedAdapter {
|
||||
public LocaleData getLocaleData();
|
||||
}
|
@ -25,14 +25,10 @@
|
||||
|
||||
package sun.util.locale.provider;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
import sun.util.calendar.ZoneInfo;
|
||||
import sun.util.resources.TimeZoneNamesBundle;
|
||||
|
||||
/**
|
||||
* Concrete implementation of the
|
||||
@ -123,9 +119,7 @@ public class TimeZoneNameProviderImpl extends TimeZoneNameProvider {
|
||||
if (id == null || locale == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type);
|
||||
TimeZoneNamesBundle rb = adapter.getLocaleResources(locale).getTimeZoneNames();
|
||||
return rb.containsKey(id) ? rb.getStringArray(id, n) : null;
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale).getTimeZoneNames(id, n);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,30 +130,6 @@ public class TimeZoneNameProviderImpl extends TimeZoneNameProvider {
|
||||
* @return an array of time zone names arrays
|
||||
*/
|
||||
String[][] getZoneStrings(Locale locale) {
|
||||
LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type);
|
||||
TimeZoneNamesBundle rb = adapter.getLocaleResources(locale).getTimeZoneNames();
|
||||
Set<String> keyset = rb.keySet();
|
||||
// Use a LinkedHashSet to preseve the order
|
||||
Set<String[]> value = new LinkedHashSet<>();
|
||||
for (String key : keyset) {
|
||||
value.add(rb.getStringArray(key));
|
||||
}
|
||||
|
||||
// Add aliases data for CLDR
|
||||
if (type == LocaleProviderAdapter.Type.CLDR) {
|
||||
// Note: TimeZoneNamesBundle creates a String[] on each getStringArray call.
|
||||
Map<String, String> aliases = ZoneInfo.getAliasTable();
|
||||
for (String alias : aliases.keySet()) {
|
||||
if (!keyset.contains(alias)) {
|
||||
String tzid = aliases.get(alias);
|
||||
if (keyset.contains(tzid)) {
|
||||
String[] val = rb.getStringArray(tzid);
|
||||
val[0] = alias;
|
||||
value.add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return value.toArray(new String[0][]);
|
||||
return LocaleProviderAdapter.forType(type).getLocaleResources(locale).getZoneStrings();
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,10 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.spi.TimeZoneNameProvider;
|
||||
import sun.util.calendar.ZoneInfo;
|
||||
import sun.util.resources.OpenListResourceBundle;
|
||||
import sun.util.resources.TimeZoneNamesBundle;
|
||||
|
||||
/**
|
||||
* Utility class that deals with the localized time zone names
|
||||
@ -44,18 +43,20 @@ import sun.util.resources.TimeZoneNamesBundle;
|
||||
*/
|
||||
public final class TimeZoneNameUtility {
|
||||
|
||||
/**
|
||||
* cache to hold time zone resource bundles. Keyed by Locale
|
||||
*/
|
||||
private static ConcurrentHashMap<Locale, SoftReference<TimeZoneNamesBundle>> cachedBundles =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* cache to hold time zone localized strings. Keyed by Locale
|
||||
*/
|
||||
private static ConcurrentHashMap<Locale, SoftReference<String[][]>> cachedZoneData =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Cache for managing display names per timezone per locale
|
||||
* The structure is:
|
||||
* Map(key=id, value=SoftReference(Map(key=locale, value=displaynames)))
|
||||
*/
|
||||
private static final Map<String, SoftReference<Map<Locale, String[]>>> cachedDisplayNames =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* get time zone localized strings. Enumerate all keys.
|
||||
*/
|
||||
@ -82,9 +83,9 @@ public final class TimeZoneNameUtility {
|
||||
}
|
||||
|
||||
// Performs per-ID retrieval.
|
||||
Set<String> zoneIDs = LocaleProviderAdapter.forJRE().getLocaleResources(locale).getZoneIDs();
|
||||
List<String[]> zones = new LinkedList<>();
|
||||
OpenListResourceBundle rb = getBundle(locale);
|
||||
for (String key : rb.keySet()) {
|
||||
for (String key : zoneIDs) {
|
||||
String[] names = retrieveDisplayNamesImpl(key, locale);
|
||||
if (names != null) {
|
||||
zones.add(names);
|
||||
@ -137,20 +138,31 @@ public final class TimeZoneNameUtility {
|
||||
private static String[] retrieveDisplayNamesImpl(String id, Locale locale) {
|
||||
LocaleServiceProviderPool pool =
|
||||
LocaleServiceProviderPool.getPool(TimeZoneNameProvider.class);
|
||||
return pool.getLocalizedObject(TimeZoneNameArrayGetter.INSTANCE, locale, id);
|
||||
}
|
||||
|
||||
private static TimeZoneNamesBundle getBundle(Locale locale) {
|
||||
TimeZoneNamesBundle rb;
|
||||
SoftReference<TimeZoneNamesBundle> data = cachedBundles.get(locale);
|
||||
|
||||
if (data == null || ((rb = data.get()) == null)) {
|
||||
rb = LocaleProviderAdapter.forJRE().getLocaleData().getTimeZoneNames(locale);
|
||||
data = new SoftReference<>(rb);
|
||||
cachedBundles.put(locale, data);
|
||||
SoftReference<Map<Locale, String[]>> ref = cachedDisplayNames.get(id);
|
||||
if (ref != null) {
|
||||
Map<Locale, String[]> perLocale = ref.get();
|
||||
if (perLocale != null) {
|
||||
String[] names = perLocale.get(locale);
|
||||
if (names != null) {
|
||||
return names;
|
||||
}
|
||||
names = pool.getLocalizedObject(TimeZoneNameArrayGetter.INSTANCE, locale, id);
|
||||
if (names != null) {
|
||||
perLocale.put(locale, names);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
}
|
||||
|
||||
return rb;
|
||||
String[] names = pool.getLocalizedObject(TimeZoneNameArrayGetter.INSTANCE, locale, id);
|
||||
if (names != null) {
|
||||
Map<Locale, String[]> perLocale = new ConcurrentHashMap<>();
|
||||
perLocale.put(locale, names);
|
||||
ref = new SoftReference<>(perLocale);
|
||||
cachedDisplayNames.put(id, ref);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,6 +98,14 @@ public class LocaleData {
|
||||
return (TimeZoneNamesBundle) getBundle(type.getUtilResourcesPackage() + ".TimeZoneNames", locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a break iterator info resource bundle, using privileges
|
||||
* to allow accessing a sun.* package.
|
||||
*/
|
||||
public ResourceBundle getBreakIteratorInfo(Locale locale) {
|
||||
return getBundle(type.getTextResourcesPackage() + ".BreakIteratorInfo", locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a collation data resource bundle, using privileges
|
||||
* to allow accessing a sun.* package.
|
||||
|
@ -80,13 +80,14 @@ package sun.util.resources.zh;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
import sun.util.resources.OpenListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_zh_HK extends OpenListResourceBundle {
|
||||
|
||||
// reparent to zh_TW for traditional Chinese names
|
||||
public CurrencyNames_zh_HK() {
|
||||
ResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getCurrencyNames(Locale.TAIWAN);
|
||||
ResourceBundle bundle = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getCurrencyNames(Locale.TAIWAN);
|
||||
setParent(bundle);
|
||||
}
|
||||
|
||||
|
@ -28,13 +28,14 @@ package sun.util.resources.zh;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
import sun.util.resources.OpenListResourceBundle;
|
||||
|
||||
public final class CurrencyNames_zh_SG extends OpenListResourceBundle {
|
||||
|
||||
// reparent to zh_CN for simplified Chinese names
|
||||
public CurrencyNames_zh_SG() {
|
||||
ResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getCurrencyNames(Locale.CHINA);
|
||||
ResourceBundle bundle = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getCurrencyNames(Locale.CHINA);
|
||||
setParent(bundle);
|
||||
}
|
||||
|
||||
|
@ -28,13 +28,14 @@ package sun.util.resources.zh;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
import sun.util.resources.OpenListResourceBundle;
|
||||
|
||||
public final class LocaleNames_zh_HK extends OpenListResourceBundle {
|
||||
|
||||
// reparent to zh_TW for traditional Chinese names
|
||||
public LocaleNames_zh_HK() {
|
||||
ResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getLocaleNames(Locale.TAIWAN);
|
||||
ResourceBundle bundle = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getLocaleNames(Locale.TAIWAN);
|
||||
setParent(bundle);
|
||||
}
|
||||
|
||||
|
@ -41,13 +41,14 @@ package sun.util.resources.zh;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
import sun.util.resources.TimeZoneNamesBundle;
|
||||
|
||||
public final class TimeZoneNames_zh_HK extends TimeZoneNamesBundle {
|
||||
|
||||
// reparent to zh_TW for traditional Chinese names
|
||||
public TimeZoneNames_zh_HK() {
|
||||
ResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getTimeZoneNames(Locale.TAIWAN);
|
||||
ResourceBundle bundle = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getTimeZoneNames(Locale.TAIWAN);
|
||||
setParent(bundle);
|
||||
}
|
||||
|
||||
|
@ -67,8 +67,7 @@ public class BreakIteratorProviderTest extends ProviderTest {
|
||||
|
||||
for (Locale target: availloc) {
|
||||
// pure JRE implementation
|
||||
ResourceBundle rb = LocaleProviderAdapter.forJRE().getLocaleData().getBundle(
|
||||
"sun.text.resources.BreakIteratorInfo", target);
|
||||
ResourceBundle rb = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getBreakIteratorInfo(target);
|
||||
String[] classNames = rb.getStringArray("BreakIteratorClasses");
|
||||
boolean jreSupportsLocale = jreimplloc.contains(target);
|
||||
|
||||
|
@ -67,7 +67,7 @@ public class CollatorProviderTest extends ProviderTest {
|
||||
for (String tag : ((AvailableLanguageTags)LocaleProviderAdapter.forJRE().getCollatorProvider()).getAvailableLanguageTags()) {
|
||||
jreimplloc.add(Locale.forLanguageTag(tag));
|
||||
}
|
||||
ResourceBundle rb = LocaleProviderAdapter.forJRE().getLocaleData().getCollationData(target);
|
||||
ResourceBundle rb = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getCollationData(target);
|
||||
boolean jreSupportsLocale = jreimplloc.contains(target);
|
||||
|
||||
// result object
|
||||
|
@ -58,7 +58,7 @@ public class CurrencyNameProviderTest extends ProviderTest {
|
||||
|
||||
for (Locale target: availloc) {
|
||||
// pure JRE implementation
|
||||
OpenListResourceBundle rb = (OpenListResourceBundle)LocaleProviderAdapter.forJRE().getLocaleData().getCurrencyNames(target);
|
||||
OpenListResourceBundle rb = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getCurrencyNames(target);
|
||||
boolean jreSupportsTarget = jreimplloc.contains(target);
|
||||
|
||||
for (Locale test: testloc) {
|
||||
|
@ -84,7 +84,7 @@ public class DateFormatProviderTest extends ProviderTest {
|
||||
break;
|
||||
}
|
||||
// pure JRE implementation
|
||||
ResourceBundle rb = LocaleProviderAdapter.forJRE().getLocaleData().getDateFormatData(target);
|
||||
ResourceBundle rb = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getDateFormatData(target);
|
||||
boolean jreSupportsLocale = jreimplloc.contains(target);
|
||||
|
||||
// JRE string arrays
|
||||
|
@ -62,7 +62,7 @@ public class DateFormatSymbolsProviderTest extends ProviderTest {
|
||||
|
||||
for (Locale target: availloc) {
|
||||
// pure JRE implementation
|
||||
ResourceBundle rb = LocaleProviderAdapter.forJRE().getLocaleData().getDateFormatData(target);
|
||||
ResourceBundle rb = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getDateFormatData(target);
|
||||
boolean jreSupportsLocale = jreimplloc.contains(target);
|
||||
|
||||
// JRE string arrays
|
||||
|
@ -61,17 +61,15 @@ public class DecimalFormatSymbolsProviderTest extends ProviderTest {
|
||||
|
||||
for (Locale target: availloc) {
|
||||
// pure JRE implementation
|
||||
ResourceBundle rb = LocaleProviderAdapter.forJRE().getLocaleData().getNumberFormatData(target);
|
||||
Object[] data = LocaleProviderAdapter.forJRE().getLocaleResources(target).getDecimalFormatSymbolsData();
|
||||
boolean jreSupportsLocale = jreimplloc.contains(target);
|
||||
|
||||
// JRE string arrays
|
||||
String[] jres = new String[2];
|
||||
if (jreSupportsLocale) {
|
||||
try {
|
||||
String[] tmp = rb.getStringArray("NumberElements");
|
||||
jres[0] = tmp[9]; // infinity
|
||||
jres[1] = tmp[10]; // NaN
|
||||
} catch (MissingResourceException mre) {}
|
||||
String[] tmp = (String[]) data[0];
|
||||
jres[0] = tmp[9]; // infinity
|
||||
jres[1] = tmp[10]; // NaN
|
||||
}
|
||||
|
||||
// result object
|
||||
|
@ -49,7 +49,7 @@ public class LocaleNameProviderTest extends ProviderTest {
|
||||
|
||||
for (Locale target: availloc) {
|
||||
// pure JRE implementation
|
||||
OpenListResourceBundle rb = LocaleProviderAdapter.forJRE().getLocaleData().getLocaleNames(target);
|
||||
OpenListResourceBundle rb = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getLocaleNames(target);
|
||||
boolean jreSupportsTarget = jreimplloc.contains(target);
|
||||
|
||||
for (Locale test: testloc) {
|
||||
|
@ -63,16 +63,12 @@ public class NumberFormatProviderTest extends ProviderTest {
|
||||
void objectValidityTest() {
|
||||
|
||||
for (Locale target: availloc) {
|
||||
// pure JRE implementation
|
||||
ResourceBundle rb = LocaleProviderAdapter.forJRE().getLocaleData().getNumberFormatData(target);
|
||||
boolean jreSupportsLocale = jreimplloc.contains(target);
|
||||
|
||||
// JRE string arrays
|
||||
String[] jreNumberPatterns = null;
|
||||
if (jreSupportsLocale) {
|
||||
try {
|
||||
jreNumberPatterns = rb.getStringArray("NumberPatterns");
|
||||
} catch (MissingResourceException mre) {}
|
||||
jreNumberPatterns = LocaleProviderAdapter.forJRE().getLocaleResources(target).getNumberPatterns();
|
||||
}
|
||||
|
||||
// result object
|
||||
|
@ -52,7 +52,7 @@ public class TimeZoneNameProviderTest extends ProviderTest {
|
||||
|
||||
for (Locale target: available) {
|
||||
// pure JRE implementation
|
||||
OpenListResourceBundle rb = LocaleProviderAdapter.forJRE().getLocaleData().getTimeZoneNames(target);
|
||||
OpenListResourceBundle rb = ((ResourceBundleBasedAdapter)LocaleProviderAdapter.forJRE()).getLocaleData().getTimeZoneNames(target);
|
||||
boolean jreSupportsTarget = jreimplloc.contains(target);
|
||||
|
||||
for (String id: ids) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user