src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java
Print this page
rev 10528 : 8038436: Re-examine the mechanism to determine available localedata and cldrdata
Reviewed-by:
@@ -23,22 +23,23 @@
* questions.
*/
package sun.util.locale.provider;
-import java.io.File;
import java.security.AccessController;
-import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import java.text.spi.BreakIteratorProvider;
import java.text.spi.CollatorProvider;
import java.text.spi.DateFormatProvider;
import java.text.spi.DateFormatSymbolsProvider;
import java.text.spi.DecimalFormatSymbolsProvider;
import java.text.spi.NumberFormatProvider;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
+import java.util.ServiceLoader;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.spi.CalendarDataProvider;
@@ -56,12 +57,10 @@
* @author Naoto Sato
* @author Masayoshi Okutsu
*/
public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements ResourceBundleBasedAdapter {
- private static final String LOCALE_DATA_JAR_NAME = "localedata.jar";
-
private final ConcurrentMap<String, Set<String>> langtagSets
= new ConcurrentHashMap<>();
private final ConcurrentMap<Locale, LocaleResources> localeResourcesMap
= new ConcurrentHashMap<>();
@@ -132,12 +131,11 @@
* Getter methods for java.text.spi.* providers
*/
@Override
public BreakIteratorProvider getBreakIteratorProvider() {
if (breakIteratorProvider == null) {
- BreakIteratorProvider provider = new BreakIteratorProviderImpl(getAdapterType(),
- getLanguageTagSet("FormatData"));
+ BreakIteratorProvider provider = new BreakIteratorProviderImpl(getAdapterType());
synchronized (this) {
if (breakIteratorProvider == null) {
breakIteratorProvider = provider;
}
}
@@ -146,12 +144,11 @@
}
@Override
public CollatorProvider getCollatorProvider() {
if (collatorProvider == null) {
- CollatorProvider provider = new CollatorProviderImpl(getAdapterType(),
- getLanguageTagSet("CollationData"));
+ CollatorProvider provider = new CollatorProviderImpl(getAdapterType());
synchronized (this) {
if (collatorProvider == null) {
collatorProvider = provider;
}
}
@@ -160,12 +157,11 @@
}
@Override
public DateFormatProvider getDateFormatProvider() {
if (dateFormatProvider == null) {
- DateFormatProvider provider = new DateFormatProviderImpl(getAdapterType(),
- getLanguageTagSet("FormatData"));
+ DateFormatProvider provider = new DateFormatProviderImpl(getAdapterType());
synchronized (this) {
if (dateFormatProvider == null) {
dateFormatProvider = provider;
}
}
@@ -174,12 +170,11 @@
}
@Override
public DateFormatSymbolsProvider getDateFormatSymbolsProvider() {
if (dateFormatSymbolsProvider == null) {
- DateFormatSymbolsProvider provider = new DateFormatSymbolsProviderImpl(getAdapterType(),
- getLanguageTagSet("FormatData"));
+ DateFormatSymbolsProvider provider = new DateFormatSymbolsProviderImpl(getAdapterType());
synchronized (this) {
if (dateFormatSymbolsProvider == null) {
dateFormatSymbolsProvider = provider;
}
}
@@ -188,11 +183,11 @@
}
@Override
public DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider() {
if (decimalFormatSymbolsProvider == null) {
- DecimalFormatSymbolsProvider provider = new DecimalFormatSymbolsProviderImpl(getAdapterType(), getLanguageTagSet("FormatData"));
+ DecimalFormatSymbolsProvider provider = new DecimalFormatSymbolsProviderImpl(getAdapterType());
synchronized (this) {
if (decimalFormatSymbolsProvider == null) {
decimalFormatSymbolsProvider = provider;
}
}
@@ -201,12 +196,11 @@
}
@Override
public NumberFormatProvider getNumberFormatProvider() {
if (numberFormatProvider == null) {
- NumberFormatProvider provider = new NumberFormatProviderImpl(getAdapterType(),
- getLanguageTagSet("FormatData"));
+ NumberFormatProvider provider = new NumberFormatProviderImpl(getAdapterType());
synchronized (this) {
if (numberFormatProvider == null) {
numberFormatProvider = provider;
}
}
@@ -218,12 +212,11 @@
* Getter methods for java.util.spi.* providers
*/
@Override
public CurrencyNameProvider getCurrencyNameProvider() {
if (currencyNameProvider == null) {
- CurrencyNameProvider provider = new CurrencyNameProviderImpl(getAdapterType(),
- getLanguageTagSet("CurrencyNames"));
+ CurrencyNameProvider provider = new CurrencyNameProviderImpl(getAdapterType());
synchronized (this) {
if (currencyNameProvider == null) {
currencyNameProvider = provider;
}
}
@@ -232,12 +225,11 @@
}
@Override
public LocaleNameProvider getLocaleNameProvider() {
if (localeNameProvider == null) {
- LocaleNameProvider provider = new LocaleNameProviderImpl(getAdapterType(),
- getLanguageTagSet("LocaleNames"));
+ LocaleNameProvider provider = new LocaleNameProviderImpl(getAdapterType());
synchronized (this) {
if (localeNameProvider == null) {
localeNameProvider = provider;
}
}
@@ -246,12 +238,11 @@
}
@Override
public TimeZoneNameProvider getTimeZoneNameProvider() {
if (timeZoneNameProvider == null) {
- TimeZoneNameProvider provider = new TimeZoneNameProviderImpl(getAdapterType(),
- getLanguageTagSet("TimeZoneNames"));
+ TimeZoneNameProvider provider = new TimeZoneNameProviderImpl(getAdapterType());
synchronized (this) {
if (timeZoneNameProvider == null) {
timeZoneNameProvider = provider;
}
}
@@ -261,12 +252,11 @@
@Override
public CalendarDataProvider getCalendarDataProvider() {
if (calendarDataProvider == null) {
CalendarDataProvider provider;
- provider = new CalendarDataProviderImpl(getAdapterType(),
- getLanguageTagSet("CalendarData"));
+ provider = new CalendarDataProviderImpl(getAdapterType());
synchronized (this) {
if (calendarDataProvider == null) {
calendarDataProvider = provider;
}
}
@@ -276,12 +266,11 @@
@Override
public CalendarNameProvider getCalendarNameProvider() {
if (calendarNameProvider == null) {
CalendarNameProvider provider;
- provider = new CalendarNameProviderImpl(getAdapterType(),
- getLanguageTagSet("FormatData"));
+ provider = new CalendarNameProviderImpl(getAdapterType());
synchronized (this) {
if (calendarNameProvider == null) {
calendarNameProvider = provider;
}
}
@@ -293,12 +282,11 @@
* Getter methods for sun.util.spi.* providers
*/
@Override
public CalendarProvider getCalendarProvider() {
if (calendarProvider == null) {
- CalendarProvider provider = new CalendarProviderImpl(getAdapterType(),
- getLanguageTagSet("CalendarData"));
+ CalendarProvider provider = new CalendarProviderImpl(getAdapterType());
synchronized (this) {
if (calendarProvider == null) {
calendarProvider = provider;
}
}
@@ -354,28 +342,58 @@
}
return tagset;
}
protected Set<String> createLanguageTagSet(String category) {
- String supportedLocaleString = LocaleDataMetaInfo.getSupportedLocaleString(category);
+ String supportedLocaleString = createSupportedLocaleString(category);
if (supportedLocaleString == null) {
return Collections.emptySet();
}
Set<String> tagset = new HashSet<>();
StringTokenizer tokens = new StringTokenizer(supportedLocaleString);
while (tokens.hasMoreTokens()) {
- String token = tokens.nextToken();
- if (token.equals("|")) {
- if (isNonENLangSupported()) {
- continue;
+ tagset.add(tokens.nextToken());
+ }
+
+ return tagset;
+ }
+
+ private static String createSupportedLocaleString(String category) {
+ // Directly call English tags, as we know it's in the base module.
+ String supportedLocaleString = JREENLocaleDataMetaInfo.getSupportedLocaleString(category);
+
+ // Use ServiceLoader to dynamically acquire installede locales' tags.
+ try {
+ String nonENTags = AccessController.doPrivileged(new PrivilegedExceptionAction<String>() {
+ @Override
+ public String run() {
+ String tags = null;
+ for (LocaleDataMetaInfo ldmi :
+ ServiceLoader.loadInstalled(LocaleDataMetaInfo.class)) {
+ if (ldmi.getType() == LocaleProviderAdapter.Type.JRE) {
+ String t = ldmi.availableLanguageTags(category);
+ if (t != null) {
+ if (tags == null) {
+ tags = t;
+ } else {
+ tags += " " + t;
+ }
}
- break;
}
- tagset.add(token);
}
+ return tags;
+ }
+ });
- return tagset;
+ if (nonENTags != null) {
+ supportedLocaleString += " " + nonENTags;
+ }
+ } catch (Exception e) {
+ // catch any exception, and ignore them as if non-EN locales do not exist.
+ }
+
+ return supportedLocaleString;
}
/**
* Lazy load available locales.
*/
@@ -385,31 +403,21 @@
}
}
private static Locale[] createAvailableLocales() {
/*
- * Gets the locale string list from LocaleDataMetaInfo class and then
+ * Gets the locale string list from LocaleDataMetaInfo classes and then
* contructs the Locale array and a set of language tags based on the
* locale string returned above.
*/
- String supportedLocaleString = LocaleDataMetaInfo.getSupportedLocaleString("AvailableLocales");
+ String supportedLocaleString = createSupportedLocaleString("AvailableLocales");
if (supportedLocaleString.length() == 0) {
throw new InternalError("No available locales for JRE");
}
- /*
- * Look for "|" and construct a new locale string list.
- */
- int barIndex = supportedLocaleString.indexOf('|');
- StringTokenizer localeStringTokenizer;
- if (isNonENLangSupported()) {
- localeStringTokenizer = new StringTokenizer(supportedLocaleString.substring(0, barIndex)
- + supportedLocaleString.substring(barIndex + 1));
- } else {
- localeStringTokenizer = new StringTokenizer(supportedLocaleString.substring(0, barIndex));
- }
+ StringTokenizer localeStringTokenizer = new StringTokenizer(supportedLocaleString);
int length = localeStringTokenizer.countTokens();
Locale[] locales = new Locale[length + 1];
locales[0] = Locale.ROOT;
for (int i = 1; i <= length; i++) {
@@ -428,41 +436,6 @@
locales[i] = Locale.forLanguageTag(currentToken);
}
}
return locales;
}
-
- private static volatile Boolean isNonENSupported = null;
-
- /*
- * Returns true if the non EN resources jar file exists in jre
- * extension directory. @returns true if the jar file is there. Otherwise,
- * returns false.
- */
- private static boolean isNonENLangSupported() {
- if (isNonENSupported == null) {
- synchronized (JRELocaleProviderAdapter.class) {
- if (isNonENSupported == null) {
- final String sep = File.separator;
- String localeDataJar =
- java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("java.home"))
- + sep + "lib" + sep + "ext" + sep + LOCALE_DATA_JAR_NAME;
-
- /*
- * Peek at the installed extension directory to see if
- * localedata.jar is installed or not.
- */
- final File f = new File(localeDataJar);
- isNonENSupported =
- AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
- @Override
- public Boolean run() {
- return f.exists();
- }
- });
- }
- }
- }
- return isNonENSupported;
- }
}