|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
/* |
|
* (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved |
|
* (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved |
|
* |
|
* The original version of this source code and documentation |
|
* is copyrighted and owned by Taligent, Inc., a wholly-owned |
|
* subsidiary of IBM. These materials are provided under terms |
|
* of a License Agreement between Taligent and Sun. This technology |
|
* is protected by multiple US and International patents. |
|
* |
|
* This notice and attribution to Taligent may not be removed. |
|
* Taligent is a registered trademark of Taligent, Inc. |
|
* |
|
*/ |
|
|
|
package sun.util.resources; |
|
|
|
import java.security.AccessController; |
|
import java.security.PrivilegedAction; |
|
import java.util.Arrays; |
|
import java.util.Iterator; |
|
import java.util.List; |
|
import java.util.Locale; |
|
import java.util.Map; |
|
import java.util.MissingResourceException; |
|
import java.util.ResourceBundle; |
|
import java.util.Set; |
|
import java.util.concurrent.ConcurrentHashMap; |
|
import java.util.spi.ResourceBundleProvider; |
|
import sun.util.locale.provider.JRELocaleProviderAdapter; |
|
import sun.util.locale.provider.LocaleProviderAdapter; |
|
import static sun.util.locale.provider.LocaleProviderAdapter.Type.CLDR; |
|
import static sun.util.locale.provider.LocaleProviderAdapter.Type.JRE; |
|
import sun.util.locale.provider.ResourceBundleBasedAdapter; |
|
|
|
/** |
|
* Provides information about and access to resource bundles in the |
|
* sun.text.resources and sun.util.resources packages or in their corresponding |
|
* packages for CLDR. |
|
* |
|
* @author Asmus Freytag |
|
* @author Mark Davis |
|
*/ |
|
|
|
public class LocaleData { |
|
private static final ResourceBundle.Control defaultControl |
|
= ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT); |
|
|
|
private static final String DOTCLDR = ".cldr"; |
|
|
|
|
|
private static final Map<String, List<Locale>> CANDIDATES_MAP = new ConcurrentHashMap<>(); |
|
|
|
private final LocaleProviderAdapter.Type type; |
|
|
|
public LocaleData(LocaleProviderAdapter.Type type) { |
|
this.type = type; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public ResourceBundle getCalendarData(Locale locale) { |
|
return getBundle(type.getUtilResourcesPackage() + ".CalendarData", locale); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public OpenListResourceBundle getCurrencyNames(Locale locale) { |
|
return (OpenListResourceBundle) getBundle(type.getUtilResourcesPackage() + ".CurrencyNames", locale); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public OpenListResourceBundle getLocaleNames(Locale locale) { |
|
return (OpenListResourceBundle) getBundle(type.getUtilResourcesPackage() + ".LocaleNames", locale); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public TimeZoneNamesBundle getTimeZoneNames(Locale locale) { |
|
return (TimeZoneNamesBundle) getBundle(type.getUtilResourcesPackage() + ".TimeZoneNames", locale); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public ResourceBundle getBreakIteratorInfo(Locale locale) { |
|
return getBundle(type.getTextResourcesPackage() + ".BreakIteratorInfo", locale); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public ResourceBundle getBreakIteratorResources(Locale locale) { |
|
return getBundle(type.getTextResourcesPackage() + ".BreakIteratorResources", locale); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public ResourceBundle getCollationData(Locale locale) { |
|
return getBundle(type.getTextResourcesPackage() + ".CollationData", locale); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public ResourceBundle getDateFormatData(Locale locale) { |
|
return getBundle(type.getTextResourcesPackage() + ".FormatData", locale); |
|
} |
|
|
|
public void setSupplementary(ParallelListResourceBundle formatData) { |
|
if (!formatData.areParallelContentsComplete()) { |
|
String suppName = type.getTextResourcesPackage() + ".JavaTimeSupplementary"; |
|
setSupplementary(suppName, formatData); |
|
} |
|
} |
|
|
|
private boolean setSupplementary(String suppName, ParallelListResourceBundle formatData) { |
|
ParallelListResourceBundle parent = (ParallelListResourceBundle) formatData.getParent(); |
|
boolean resetKeySet = false; |
|
if (parent != null) { |
|
resetKeySet = setSupplementary(suppName, parent); |
|
} |
|
OpenListResourceBundle supp = getSupplementary(suppName, formatData.getLocale()); |
|
formatData.setParallelContents(supp); |
|
resetKeySet |= supp != null; |
|
// If any parents or this bundle has parallel data, reset keyset to create |
|
|
|
if (resetKeySet) { |
|
formatData.resetKeySet(); |
|
} |
|
return resetKeySet; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public ResourceBundle getNumberFormatData(Locale locale) { |
|
return getBundle(type.getTextResourcesPackage() + ".FormatData", locale); |
|
} |
|
|
|
public static ResourceBundle getBundle(final String baseName, final Locale locale) { |
|
return AccessController.doPrivileged(new PrivilegedAction<>() { |
|
@Override |
|
public ResourceBundle run() { |
|
return Bundles.of(baseName, locale, LocaleDataStrategy.INSTANCE); |
|
} |
|
}); |
|
} |
|
|
|
private static OpenListResourceBundle getSupplementary(final String baseName, final Locale locale) { |
|
return AccessController.doPrivileged(new PrivilegedAction<>() { |
|
@Override |
|
public OpenListResourceBundle run() { |
|
OpenListResourceBundle rb = null; |
|
try { |
|
rb = (OpenListResourceBundle) Bundles.of(baseName, locale, |
|
SupplementaryStrategy.INSTANCE); |
|
} catch (MissingResourceException e) { |
|
// return null if no supplementary is available |
|
} |
|
return rb; |
|
} |
|
}); |
|
} |
|
|
|
private static abstract class LocaleDataResourceBundleProvider |
|
implements ResourceBundleProvider { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
protected String toBundleName(String baseName, Locale locale) { |
|
return LocaleDataStrategy.INSTANCE.toBundleName(baseName, locale); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static abstract class CommonResourceBundleProvider extends LocaleDataResourceBundleProvider { |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static abstract class SupplementaryResourceBundleProvider extends LocaleDataResourceBundleProvider { |
|
} |
|
|
|
// Bundles.Strategy implementations |
|
|
|
private static class LocaleDataStrategy implements Bundles.Strategy { |
|
private static final LocaleDataStrategy INSTANCE = new LocaleDataStrategy(); |
|
|
|
private static Set<Locale> JAVA_BASE_LOCALES |
|
= Set.of(Locale.ROOT, Locale.ENGLISH, Locale.US, new Locale("en", "US", "POSIX")); |
|
|
|
private LocaleDataStrategy() { |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public List<Locale> getCandidateLocales(String baseName, Locale locale) { |
|
String key = baseName + '-' + locale.toLanguageTag(); |
|
List<Locale> candidates = CANDIDATES_MAP.get(key); |
|
if (candidates == null) { |
|
LocaleProviderAdapter.Type type = baseName.contains(DOTCLDR) ? CLDR : JRE; |
|
LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type); |
|
candidates = adapter instanceof ResourceBundleBasedAdapter ? |
|
((ResourceBundleBasedAdapter)adapter).getCandidateLocales(baseName, locale) : |
|
defaultControl.getCandidateLocales(baseName, locale); |
|
|
|
|
|
int lastDot = baseName.lastIndexOf('.'); |
|
String category = (lastDot >= 0) ? baseName.substring(lastDot + 1) : baseName; |
|
Set<String> langtags = ((JRELocaleProviderAdapter)adapter).getLanguageTagSet(category); |
|
if (!langtags.isEmpty()) { |
|
for (Iterator<Locale> itr = candidates.iterator(); itr.hasNext();) { |
|
if (!adapter.isSupportedProviderLocale(itr.next(), langtags)) { |
|
itr.remove(); |
|
} |
|
} |
|
} |
|
CANDIDATES_MAP.putIfAbsent(key, candidates); |
|
} |
|
return candidates; |
|
} |
|
|
|
boolean inJavaBaseModule(String baseName, Locale locale) { |
|
return JAVA_BASE_LOCALES.contains(locale); |
|
} |
|
|
|
@Override |
|
public String toBundleName(String baseName, Locale locale) { |
|
String newBaseName = baseName; |
|
if (!inJavaBaseModule(baseName, locale)) { |
|
if (baseName.startsWith(JRE.getUtilResourcesPackage()) |
|
|| baseName.startsWith(JRE.getTextResourcesPackage())) { |
|
|
|
assert JRE.getUtilResourcesPackage().length() |
|
== JRE.getTextResourcesPackage().length(); |
|
int index = JRE.getUtilResourcesPackage().length(); |
|
if (baseName.indexOf(DOTCLDR, index) > 0) { |
|
index += DOTCLDR.length(); |
|
} |
|
newBaseName = baseName.substring(0, index + 1) + "ext" |
|
+ baseName.substring(index); |
|
} |
|
} |
|
return defaultControl.toBundleName(newBaseName, locale); |
|
} |
|
|
|
@Override |
|
public Class<? extends ResourceBundleProvider> getResourceBundleProviderType(String baseName, |
|
Locale locale) { |
|
return inJavaBaseModule(baseName, locale) ? |
|
null : CommonResourceBundleProvider.class; |
|
} |
|
} |
|
|
|
private static class SupplementaryStrategy extends LocaleDataStrategy { |
|
private static final SupplementaryStrategy INSTANCE |
|
= new SupplementaryStrategy(); |
|
|
|
private static Set<Locale> JAVA_BASE_LOCALES |
|
= Set.of(Locale.ROOT, Locale.ENGLISH, Locale.US); |
|
|
|
private SupplementaryStrategy() { |
|
} |
|
|
|
@Override |
|
public List<Locale> getCandidateLocales(String baseName, Locale locale) { |
|
|
|
return Arrays.asList(locale); |
|
} |
|
|
|
@Override |
|
public Class<? extends ResourceBundleProvider> getResourceBundleProviderType(String baseName, |
|
Locale locale) { |
|
return inJavaBaseModule(baseName, locale) ? |
|
null : SupplementaryResourceBundleProvider.class; |
|
} |
|
|
|
@Override |
|
boolean inJavaBaseModule(String baseName, Locale locale) { |
|
return JAVA_BASE_LOCALES.contains(locale); |
|
} |
|
} |
|
} |