提交 bb45e575 编写于 作者: N naoto

7162007: Clean up i18n related caches

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