8038436: Re-examine the mechanism to determine available localedata and cldrdata

Reviewed-by: alanb, mchung, okutsu
This commit is contained in:
Naoto Sato 2014-09-02 14:11:38 -07:00
parent 62b9ab4a81
commit 2cbff3dfc4
13 changed files with 438 additions and 124 deletions

View File

@ -76,13 +76,24 @@ LOCALEDATA_INCLUDE_LOCALES := ar be bg ca cs da de el es et fi fr ga hi hr hu in
iw ja ko lt lv mk ms mt nl no pl pt ro ru sk sl sq sr sv \
th tr uk vi zh
LOCALEDATA_INCLUDES := $(addprefix sun/text/resources/, $(LOCALEDATA_INCLUDE_LOCALES)) \
LOCALEDATA_INCLUDES := sun/util/resources/provider/NonEnLocaleDataMetaInfo.class
LOCALEDATA_INCLUDES += $(addprefix sun/text/resources/, $(LOCALEDATA_INCLUDE_LOCALES)) \
$(addprefix sun/util/resources/, $(LOCALEDATA_INCLUDE_LOCALES))
$(eval $(call SetupArchive,BUILD_LOCALEDATA_JAR, , \
SRCS := $(JDK_OUTPUTDIR)/modules/jdk.localedata, \
LOCALEDATA_SERVICES_DIR := $(IMAGES_OUTPUTDIR)/localemetainfo
LOCALEDATA_METAINF_SERVICES := $(LOCALEDATA_SERVICES_DIR)/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo
$(LOCALEDATA_METAINF_SERVICES): $(JDK_TOPDIR)/src/jdk.localedata/META-INF/localedata-services/sun.util.locale.provider.LocaleDataMetaInfo
$(install-file)
$(eval $(call SetupArchive,BUILD_LOCALEDATA_JAR, \
$(LOCALEDATA_METAINF_SERVICES), \
SRCS := $(JDK_OUTPUTDIR)/modules/jdk.localedata \
$(LOCALEDATA_SERVICES_DIR), \
SUFFIXES := .class _dict _th, \
INCLUDES := $(LOCALEDATA_INCLUDES), \
EXTRA_FILES := META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo, \
JAR := $(IMAGES_OUTPUTDIR)/lib/ext/localedata.jar, \
SKIP_METAINF := true))
@ -210,6 +221,8 @@ RT_JAR_EXCLUDES += \
sun/tools/tree \
sun/tools/util \
sun/util/cldr/CLDRLocaleDataMetaInfo.class \
sun/util/resources/provider/NonEnLocaleDataMetaInfo.class \
META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo \
sun/util/resources/cldr \
$(LOCALEDATA_INCLUDES) \
com/oracle/jrockit/jfr \
@ -429,13 +442,23 @@ include gensrc/GensrcCLDR.gmk
CLDRDATA_JAR_DST := $(IMAGES_OUTPUTDIR)/lib/ext/cldrdata.jar
$(eval $(call SetupArchive,BUILD_CLDRDATA_JAR, , \
CLDR_SERVICES_DIR := $(IMAGES_OUTPUTDIR)/cldrmetainfo
CLDR_METAINF_SERVICES := $(CLDR_SERVICES_DIR)/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo
$(CLDR_METAINF_SERVICES): $(JDK_TOPDIR)/src/jdk.localedata/META-INF/cldrdata-services/sun.util.locale.provider.LocaleDataMetaInfo
$(install-file)
$(eval $(call SetupArchive,BUILD_CLDRDATA_JAR, \
$(CLDR_METAINF_SERVICES), \
SRCS := $(JDK_OUTPUTDIR)/modules/jdk.localedata \
$(JDK_OUTPUTDIR)/modules/java.base, \
$(JDK_OUTPUTDIR)/modules/java.base \
$(CLDR_SERVICES_DIR), \
SUFFIXES := .class, \
INCLUDES := sun/text/resources/cldr \
sun/util/cldr/CLDRLocaleDataMetaInfo.class \
sun/util/resources/cldr, \
EXTRA_FILES := META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo, \
JAR := $(CLDRDATA_JAR_DST), \
EXTRA_MANIFEST_ATTR := CLDR-Version: $(CLDRVERSION), \
SKIP_METAINF := true))

View File

@ -58,7 +58,14 @@ EN_LOCALES := en%
# Locales that don't have any resource files should be included here.
ALL_NON_EN_LOCALES := ja-JP-JP nb-NO nn-NO th-TH-TH
SED_ARGS := -e 's|$(HASH)warn This file is preprocessed before being compiled|// -- This file was mechanically generated: Do not edit! -- //|g'
SED_ENARGS := -e 's|$(HASH)warn This file is preprocessed before being compiled|// -- This file was mechanically generated: Do not edit! -- //|g'
SED_NONENARGS := $(SED_ENARGS)
# Fill in the languages and package names
SED_ENARGS += -e 's/$(HASH)Lang$(HASH)/En/' \
-e 's/$(HASH)Package$(HASH)/sun.util.locale.provider/'
SED_NONENARGS += -e 's/$(HASH)Lang$(HASH)/NonEn/' \
-e 's/$(HASH)Package$(HASH)/sun.util.resources.provider/'
# This macro creates a sed expression that substitues for example:
# #FormatData_ENLocales# with: en% locales.
@ -78,8 +85,8 @@ define CaptureLocale
ALL_NON_EN_LOCALES += $$($1_NON_EN_LOCALES)
# Don't sed in a space if there are no locales.
SED_ARGS += -e 's/$$(HASH)$1_ENLocales$$(HASH)/$$(if $$($1_EN_LOCALES),$$(SPACE)$$($1_EN_LOCALES),)/g'
SED_ARGS += -e 's/$$(HASH)$1_NonENLocales$$(HASH)/$$(if $$($1_NON_EN_LOCALES),$$(SPACE)$$($1_NON_EN_LOCALES),)/g'
SED_ENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_EN_LOCALES),$$(SPACE)$$($1_EN_LOCALES),)/g'
SED_NONENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_NON_EN_LOCALES),$$(SPACE)$$($1_NON_EN_LOCALES),)/g'
endef
#sun.text.resources.FormatData
@ -106,17 +113,25 @@ $(eval $(call CaptureLocale,CurrencyNames))
#sun.util.resources.CalendarData
$(eval $(call CaptureLocale,CalendarData))
SED_ARGS += -e 's/$(HASH)AvailableLocales_ENLocales$(HASH)/$(sort $(ALL_EN_LOCALES))/g'
SED_ARGS += -e 's/$(HASH)AvailableLocales_NonENLocales$(HASH)/$(sort $(ALL_NON_EN_LOCALES))/g'
SED_ENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_EN_LOCALES))/g'
SED_NONENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_NON_EN_LOCALES))/g'
$(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/LocaleDataMetaInfo.java: \
$(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java: \
$(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template
$(MKDIR) -p $(@D)
$(ECHO) Creating sun/util/LocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources.
$(ECHO) Creating sun/util/locale/provider/EnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources.
$(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources
$(SED) $(SED_ARGS) $< > $@
$(SED) $(SED_ENARGS) $< > $@
GENSRC_LOCALEDATAMETAINFO := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/LocaleDataMetaInfo.java
$(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java: \
$(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template
$(MKDIR) -p $(@D)
$(ECHO) Creating sun/util/resources/provider/NonEnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources.
$(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources
$(SED) $(SED_NONENARGS) $< > $@
GENSRC_LOCALEDATAMETAINFO := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java \
$(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java
################################################################################

View File

@ -431,7 +431,7 @@ public class CLDRConverter {
allLocales.addAll(metaInfo.get("LocaleNames"));
allLocales.addAll(metaInfo.get("CalendarData"));
allLocales.addAll(metaInfo.get("FormatData"));
metaInfo.put("All", allLocales);
metaInfo.put("AvailableLocales", allLocales);
}
bundleGenerator.generateMetaInfo(metaInfo);

View File

@ -159,8 +159,10 @@ class ResourceBundleGenerator implements BundleGenerator {
out.println(CopyrightHeaders.getOpenJDKCopyright());
out.println("package sun.util.cldr;\n\n"
+ "import java.util.ListResourceBundle;\n");
out.printf("public class %s extends ListResourceBundle {\n", METAINFO_CLASS);
+ "import java.util.ListResourceBundle;\n"
+ "import sun.util.locale.provider.LocaleProviderAdapter;\n"
+ "import sun.util.locale.provider.LocaleDataMetaInfo;\n");
out.printf("public class %s extends ListResourceBundle implements LocaleDataMetaInfo {\n", METAINFO_CLASS);
out.println(" @Override\n" +
" protected final Object[][] getContents() {\n" +
" final Object[][] data = new Object[][] {");
@ -168,7 +170,15 @@ class ResourceBundleGenerator implements BundleGenerator {
out.printf(" { \"%s\",\n", key);
out.printf(" \"%s\" },\n", toLocaleList(metaInfo.get(key)));
}
out.println(" };\n return data;\n }\n}");
out.println(" };\n return data;\n }\n\n");
out.println(" public LocaleProviderAdapter.Type getType() {\n" +
" return LocaleProviderAdapter.Type.CLDR;\n" +
" }\n\n");
out.println(" public String availableLanguageTags(String category) {\n" +
" return getString(category);\n" +
" };\n}");
}
}

View File

@ -25,20 +25,20 @@
package sun.util.cldr;
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.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.spi.TimeZoneNameProvider;
import sun.util.locale.provider.JRELocaleProviderAdapter;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleDataMetaInfo;
/**
* LocaleProviderAdapter implementation for the CLDR locale data.
@ -47,26 +47,31 @@ import sun.util.locale.provider.LocaleProviderAdapter;
* @author Naoto Sato
*/
public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
private static final String LOCALE_DATA_JAR_NAME = "cldrdata.jar";
private final LocaleDataMetaInfo metaInfo;
public CLDRLocaleProviderAdapter() {
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 the jar file for
// CLDR resources is installed or not.
final File f = new File(localeDataJar);
boolean result = AccessController.doPrivileged(
new PrivilegedAction<Boolean>() {
try {
metaInfo = AccessController.doPrivileged(new PrivilegedExceptionAction<LocaleDataMetaInfo>() {
@Override
public Boolean run() {
return f.exists();
public LocaleDataMetaInfo run() {
for (LocaleDataMetaInfo ldmi : ServiceLoader.loadInstalled(LocaleDataMetaInfo.class)) {
if (ldmi.getType() == LocaleProviderAdapter.Type.CLDR) {
return ldmi;
}
}
return null;
}
});
if (!result) {
throw new UnsupportedOperationException();
} catch (Exception e) {
// Catch any exception, and fail gracefully as if CLDR locales do not exist.
// It's ok ignore it if something wrong happens because there always is the
// JRE or FALLBACK LocaleProviderAdapter that will do the right thing.
throw new UnsupportedOperationException(e);
}
if (metaInfo == null) {
throw new UnsupportedOperationException("CLDR locale data could not be found.");
}
}
@ -91,7 +96,7 @@ public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
@Override
public Locale[] getAvailableLocales() {
Set<String> all = createLanguageTagSet("All");
Set<String> all = createLanguageTagSet("AvailableLocales");
Locale[] locs = new Locale[all.size()];
int index = 0;
for (String tag : all) {
@ -102,11 +107,10 @@ public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter {
@Override
protected Set<String> createLanguageTagSet(String category) {
ResourceBundle rb = ResourceBundle.getBundle("sun.util.cldr.CLDRLocaleDataMetaInfo", Locale.ROOT);
if (rb.containsKey(category)) {
String supportedLocaleString = metaInfo.availableLanguageTags(category);
if (supportedLocaleString == null) {
return Collections.emptySet();
}
String supportedLocaleString = rb.getString(category);
Set<String> tagset = new HashSet<>();
StringTokenizer tokens = new StringTokenizer(supportedLocaleString);
while (tokens.hasMoreTokens()) {

View File

@ -56,7 +56,7 @@ public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter {
/**
* SPI implementations map
*/
private ConcurrentMap<Class<? extends LocaleServiceProvider>, LocaleServiceProvider> providersMap =
private final ConcurrentMap<Class<? extends LocaleServiceProvider>, LocaleServiceProvider> providersMap =
new ConcurrentHashMap<>();
/**
@ -167,7 +167,6 @@ public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter {
avail.addAll(Arrays.asList(lsp.getAvailableLocales()));
}
}
availableLocales = avail.toArray(new Locale[0]);
}
// assuming caller won't mutate the array.
@ -178,7 +177,7 @@ public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter {
* A dummy locale service provider that indicates there is no
* provider available
*/
private static NullProvider NULL_PROVIDER = new NullProvider();
private static final NullProvider NULL_PROVIDER = new NullProvider();
private static class NullProvider extends LocaleServiceProvider {
@Override
public Locale[] getAvailableLocales() {

View File

@ -25,9 +25,9 @@
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;
@ -37,6 +37,7 @@ 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;
@ -58,8 +59,6 @@ import sun.util.spi.CalendarProvider;
*/
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<>();
@ -356,26 +355,56 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R
}
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;
}
break;
}
tagset.add(token);
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 = EnLocaleDataMetaInfo.getSupportedLocaleString(category);
// Use ServiceLoader to dynamically acquire installed 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;
}
}
}
}
return tags;
}
});
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.
*/
@ -387,27 +416,17 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R
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];
@ -430,39 +449,4 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R
}
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;
}
}

View File

@ -30,19 +30,17 @@
* each resource in sun.util.resources & sun.text.resources.
* It is used to avoid loading non-existent localized resources so that
* jar files won't be opened unnecessary to look up them.
*
* @since 1.6
*/
package sun.util.locale.provider;
package #Package#;
import java.util.HashMap;
import java.util.Map;
import sun.util.locale.provider.LocaleDataMetaInfo;
import static sun.util.locale.provider.LocaleProviderAdapter.Type;
public class #Lang#LocaleDataMetaInfo implements LocaleDataMetaInfo {
public class LocaleDataMetaInfo {
private static final HashMap<String, String> resourceNameToLocales =
new HashMap<String, String>(7);
private static final Map<String, String> resourceNameToLocales = new HashMap<>(9);
static {
/* During JDK build time, #XXX_YYY# will be replaced by a string contain all the locales
@ -52,38 +50,51 @@ public class LocaleDataMetaInfo {
look up locale string such as "en" could be based on if it contains " en ".
*/
resourceNameToLocales.put("FormatData",
" #FormatData_ENLocales# | #FormatData_NonENLocales# ");
" #FormatData_Locales# ");
resourceNameToLocales.put("CollationData",
" #CollationData_ENLocales# | #CollationData_NonENLocales# ");
" #CollationData_Locales# ");
resourceNameToLocales.put("BreakIteratorInfo",
" #BreakIteratorInfo_ENLocales# | #BreakIteratorInfo_NonENLocales# ");
" #BreakIteratorInfo_Locales# ");
resourceNameToLocales.put("BreakIteratorRules",
" #BreakIteratorRules_ENLocales# | #BreakIteratorRules_NonENLocales# ");
" #BreakIteratorRules_Locales# ");
resourceNameToLocales.put("TimeZoneNames",
" #TimeZoneNames_ENLocales# | #TimeZoneNames_NonENLocales# ");
" #TimeZoneNames_Locales# ");
resourceNameToLocales.put("LocaleNames",
" #LocaleNames_ENLocales# | #LocaleNames_NonENLocales# ");
" #LocaleNames_Locales# ");
resourceNameToLocales.put("CurrencyNames",
" #CurrencyNames_ENLocales# | #CurrencyNames_NonENLocales# ");
" #CurrencyNames_Locales# ");
resourceNameToLocales.put("CalendarData",
" #CalendarData_ENLocales# | #CalendarData_NonENLocales# ");
" #CalendarData_Locales# ");
resourceNameToLocales.put("AvailableLocales",
" #AvailableLocales_ENLocales# | #AvailableLocales_NonENLocales# ");
" #AvailableLocales_Locales# ");
}
/*
* Gets the supported locales string based on the availability of
* locale data resource bundles for each resource name.
*
* @param resourceName the resource name
* @return the supported locale string for the passed in resource.
*/
public static String getSupportedLocaleString(String resourceName) {
return resourceNameToLocales.get(resourceName);
return resourceNameToLocales.getOrDefault(resourceName, "");
}
@Override
public Type getType() {
return Type.JRE;
}
@Override
public String availableLanguageTags(String category) {
return getSupportedLocaleString(category);
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2014, 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;
/**
* LocaleData meta info SPI
*
* @author Naoto Sato
*/
public interface LocaleDataMetaInfo {
/**
* Returns the type of LocaleProviderAdapter for which this LocaleData
* provides the data.
* @return type The type of the adapter.
*/
public LocaleProviderAdapter.Type getType();
/**
* Returns the string concatenation of the supported language tags in
* this LocaleData instance
* @param category category of the locale data.
* @return concatenated language tags, separated by a space.
*/
public String availableLanguageTags(String category);
}

View File

@ -50,7 +50,6 @@ import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import sun.util.locale.provider.JRELocaleProviderAdapter;
import sun.util.locale.provider.LocaleDataMetaInfo;
import sun.util.locale.provider.LocaleProviderAdapter;
import static sun.util.locale.provider.LocaleProviderAdapter.Type.CLDR;
import static sun.util.locale.provider.LocaleProviderAdapter.Type.JRE;

View File

@ -0,0 +1 @@
sun.util.cldr.CLDRLocaleDataMetaInfo

View File

@ -0,0 +1 @@
sun.util.resources.provider.NonEnLocaleDataMetaInfo

View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 2014, 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.
*
* 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.
*/
/*
* @test
* @bug 8038436
* @summary Test for changes in 8038436
* @compile -XDignore.symbol.file Bug8038436.java
* @run main/othervm Bug8038436 -Djava.ext.dirs=foo security
* @run main/othervm Bug8038436 -Djava.locale.providers=JRE availlocs
*/
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.stream.*;
import sun.util.locale.provider.*;
public class Bug8038436 {
public static void main(String[] args) {
switch (args[1]) {
case "security":
securityTests();
break;
case "availlocs":
availableLocalesTests();
break;
default:
throw new RuntimeException("no test was specified.");
}
}
private static void securityTests() {
Policy.setPolicy(new MyPolicy());
System.setSecurityManager(new SecurityManager());
/*
* Test for AccessClassInPackage security exception. Confirms that
* exeption won't be thrown if an application sets a Permission that
* does not allow any RuntimePermission, on loading LocaleDataMetaInfo
* from jdk.localedata module.
*/
System.out.println(new Formatter(Locale.JAPAN).format("%1$tB %1$te, %1$tY",
new GregorianCalendar()));
/*
* Check only English/ROOT locales are returned if the jdk.localedata
* module is not installed (implied by "java.ext.dirs" set to "foo").
*/
if (Arrays.asList(Locale.getAvailableLocales())
.stream()
.anyMatch(l -> l != Locale.ROOT && l.getLanguage() != "en")) {
throw new RuntimeException("non English locale(s) included in available locales");
}
}
static class MyPolicy extends Policy {
final PermissionCollection perms = new Permissions();
MyPolicy() {
// allows no RuntimePermission
}
public PermissionCollection getPermissions(ProtectionDomain domain) {
return perms;
}
public PermissionCollection getPermissions(CodeSource codesource) {
return perms;
}
public boolean implies(ProtectionDomain domain, Permission perm) {
return perms.implies(perm);
}
}
static final String[] bipLocs = ("ar, ar-JO, ar-LB, ar-SY, be, be-BY, bg, " +
"bg-BG, ca, ca-ES, cs, cs-CZ, da, da-DK, de, de-AT, de-CH, de-DE, " +
"de-LU, el, el-CY, el-GR, en, en-AU, en-CA, en-GB, en-IE, en-IN, " +
"en-MT, en-NZ, en-PH, en-SG, en-US, en-ZA, es, es-AR, es-BO, es-CL, " +
"es-CO, es-CR, es-DO, es-EC, es-ES, es-GT, es-HN, es-MX, es-NI, " +
"es-PA, es-PE, es-PR, es-PY, es-SV, es-US, es-UY, es-VE, et, et-EE, " +
"fi, fi-FI, fr, fr-BE, fr-CA, fr-CH, fr-FR, ga, ga-IE, he, he-IL, " +
"hi-IN, hr, hr-HR, hu, hu-HU, id, id-ID, is, is-IS, it, it-CH, it-IT, " +
"ja, ja-JP, ko, ko-KR, lt, lt-LT, lv, lv-LV, mk, mk-MK, ms, ms-MY, mt, " +
"mt-MT, nl, nl-BE, nl-NL, no, no-NO, no-NO, pl, pl-PL, pt, pt-BR, " +
"pt-PT, ro, ro-RO, ru, ru-RU, sk, sk-SK, sl, sl-SI, sq, sq-AL, sr, " +
"sr-BA, sr-CS, sr-Latn, sr-Latn-ME, sr-ME, sr-RS, sv, sv-SE, th, th-TH, " +
"tr, tr-TR, uk, uk-UA, und, vi, vi-VN, zh, zh-CN, zh-HK, zh-Hans-CN, " +
"zh-Hans-SG, zh-Hant-HK, zh-Hant-TW, zh-SG, zh-TW, ").split(",\\s*");
static final String[] dfpLocs = bipLocs;
static final String[] datefspLocs = bipLocs;
static final String[] decimalfspLocs = bipLocs;
static final String[] calnpLocs = bipLocs;
static final String[] cpLocs = ("ar, be, bg, ca, cs, da, el, es, et, fi, " +
"fr, he, hi, hr, hu, is, ja, ko, lt, lv, mk, no, pl, ro, ru, sk, sl, " +
"sq, sr, sr-Latn, sv, th, tr, uk, und, vi, zh, zh-HK, zh-Hant-HK, " +
"zh-Hant-TW, zh-TW, ").split(",\\s*");
static final String[] nfpLocs = ("ar, ar-AE, ar-BH, ar-DZ, ar-EG, ar-IQ, " +
"ar-JO, ar-KW, ar-LB, ar-LY, ar-MA, ar-OM, ar-QA, ar-SA, ar-SD, ar-SY, " +
"ar-TN, ar-YE, be, be-BY, bg, bg-BG, ca, ca-ES, cs, cs-CZ, da, da-DK, " +
"de, de-AT, de-CH, de-DE, de-GR, de-LU, el, el-CY, el-GR, en, en-AU, " +
"en-CA, en-GB, en-IE, en-IN, en-MT, en-NZ, en-PH, en-SG, en-US, en-ZA, " +
"es, es-AR, es-BO, es-CL, es-CO, es-CR, es-CU, es-DO, es-EC, es-ES, " +
"es-GT, es-HN, es-MX, es-NI, es-PA, es-PE, es-PR, es-PY, es-SV, es-US, " +
"es-UY, es-VE, et, et-EE, fi, fi-FI, fr, fr-BE, fr-CA, fr-CH, fr-FR, " +
"fr-LU, ga, ga-IE, he, he-IL, hi, hi-IN, hr, hr-HR, hu, hu-HU, id, " +
"id-ID, is, is-IS, it, it-CH, it-IT, ja, ja-JP, " +
"ja-JP-u-ca-japanese-x-lvariant-JP, ko, ko-KR, lt, lt-LT, lv, lv-LV, " +
"mk, mk-MK, ms, ms-MY, mt, mt-MT, nb-NO, nl, nl-BE, nl-NL, nn-NO, " +
"nn-NO, no, no-NO, pl, pl-PL, pt, pt-BR, pt-PT, ro, ro-RO, ru, ru-RU, " +
"sk, sk-SK, sl, sl-SI, sq, sq-AL, sr, sr-BA, sr-CS, sr-Latn, " +
"sr-Latn-BA, sr-Latn-ME, sr-Latn-RS, sr-ME, sr-RS, sv, sv-SE, th, " +
"th-TH, th-TH-u-nu-thai-x-lvariant-TH, tr, tr-TR, uk, uk-UA, und, vi, " +
"vi-VN, zh, zh-CN, zh-HK, zh-Hans-CN, zh-Hans-SG, zh-Hant-HK, " +
"zh-Hant-TW, zh-SG, zh-TW, ").split(",\\s*");
static final String[] currencynpLocs = ("ar-AE, ar-BH, ar-DZ, ar-EG, ar-IQ, " +
"ar-JO, ar-KW, ar-LB, ar-LY, ar-MA, ar-OM, ar-QA, ar-SA, ar-SD, ar-SY, " +
"ar-TN, ar-YE, be-BY, bg-BG, ca-ES, cs-CZ, da-DK, de, de-AT, de-CH, " +
"de-DE, de-GR, de-LU, el-CY, el-GR, en-AU, en-CA, en-GB, en-IE, en-IN, " +
"en-MT, en-NZ, en-PH, en-SG, en-US, en-ZA, es, es-AR, es-BO, es-CL, " +
"es-CO, es-CR, es-CU, es-DO, es-EC, es-ES, es-GT, es-HN, es-MX, es-NI, " +
"es-PA, es-PE, es-PR, es-PY, es-SV, es-US, es-UY, es-VE, et-EE, fi-FI, " +
"fr, fr-BE, fr-CA, fr-CH, fr-FR, fr-LU, ga-IE, he-IL, hi-IN, hr-HR, " +
"hu-HU, id-ID, is-IS, it, it-CH, it-IT, ja, ja-JP, ko, ko-KR, lt-LT, " +
"lv-LV, mk-MK, ms-MY, mt-MT, nl-BE, nl-NL, no-NO, pl-PL, pt, pt-BR, " +
"pt-PT, ro-RO, ru-RU, sk-SK, sl-SI, sq-AL, sr-BA, sr-CS, sr-Latn-BA, " +
"sr-Latn-ME, sr-Latn-RS, sr-ME, sr-RS, sv, sv-SE, th-TH, tr-TR, uk-UA, " +
"und, vi-VN, zh-CN, zh-HK, zh-Hans-CN, zh-Hans-SG, zh-Hant-HK, " +
"zh-Hant-TW, zh-SG, zh-TW, ").split(",\\s*");
static final String[] lnpLocs = ("ar, be, bg, ca, cs, da, de, el, el-CY, " +
"en, en-MT, en-PH, en-SG, es, es-US, et, fi, fr, ga, he, hi, hr, hu, " +
"id, is, it, ja, ko, lt, lv, mk, ms, mt, nl, no, no-NO, pl, pt, pt-BR, " +
"pt-PT, ro, ru, sk, sl, sq, sr, sr-Latn, sv, th, tr, uk, und, vi, zh, " +
"zh-HK, zh-Hans-SG, zh-Hant-HK, zh-Hant-TW, zh-SG, zh-TW, ").split(",\\s*");
static final String[] tznpLocs = ("de, en, en-CA, en-GB, en-IE, es, fr, hi, " +
"it, ja, ko, pt-BR, sv, und, zh-CN, zh-HK, zh-Hans-CN, zh-Hant-HK, " +
"zh-Hant-TW, zh-TW, ").split(",\\s*");
static final String[] caldpLocs = ("ar, be, bg, ca, cs, da, de, el, el-CY, " +
"en, en-GB, en-IE, en-MT, es, es-ES, es-US, et, fi, fr, fr-CA, he, hi, " +
"hr, hu, id-ID, is, it, ja, ko, lt, lv, mk, ms-MY, mt, mt-MT, nl, no, " +
"pl, pt, pt-BR, pt-PT, ro, ru, sk, sl, sq, sr, sr-Latn-BA, sr-Latn-ME, " +
"sr-Latn-RS, sv, th, tr, uk, und, vi, zh, ").split(",\\s*");
static final String[] calpLocs = caldpLocs;
/*
* Validate whether JRE's *Providers return supported locales list based on
* their actual resource bundle exsistence. The above golden data
* are manually extracted, so they need to be updated if new locale
* data resource bundle were added.
*/
private static void availableLocalesTests() {
LocaleProviderAdapter jre = LocaleProviderAdapter.forJRE();
checkAvailableLocales("BreakIteratorProvider",
jre.getBreakIteratorProvider().getAvailableLocales(), bipLocs);
checkAvailableLocales("CollatorProvider",
jre.getCollatorProvider().getAvailableLocales(), cpLocs);
checkAvailableLocales("DateFormatProvider",
jre.getDateFormatProvider().getAvailableLocales(), dfpLocs);
checkAvailableLocales("DateFormatSymbolsProvider",
jre.getDateFormatSymbolsProvider().getAvailableLocales(), datefspLocs);
checkAvailableLocales("DecimalFormatSymbolsProvider",
jre.getDecimalFormatSymbolsProvider().getAvailableLocales(), decimalfspLocs);
checkAvailableLocales("NumberFormatProvider",
jre.getNumberFormatProvider().getAvailableLocales(), nfpLocs);
checkAvailableLocales("CurrencyNameProvider",
jre.getCurrencyNameProvider().getAvailableLocales(), currencynpLocs);
checkAvailableLocales("LocaleNameProvider",
jre.getLocaleNameProvider().getAvailableLocales(), lnpLocs);
checkAvailableLocales("TimeZoneNameProvider",
jre.getTimeZoneNameProvider().getAvailableLocales(), tznpLocs);
checkAvailableLocales("CalendarDataProvider",
jre.getCalendarDataProvider().getAvailableLocales(), caldpLocs);
checkAvailableLocales("CalendarNameProvider",
jre.getCalendarNameProvider().getAvailableLocales(), calnpLocs);
checkAvailableLocales("CalendarProvider",
jre.getCalendarProvider().getAvailableLocales(), calpLocs);
}
private static void checkAvailableLocales(String testName, Locale[] got, String[] expected) {
System.out.println("Testing available locales for " + testName);
List<Locale> gotList = Arrays.asList(got).stream()
.map(Locale::toLanguageTag)
.sorted()
.map(Locale::forLanguageTag)
.collect(Collectors.toList());
List<Locale> expectedList = Arrays.asList(expected).stream()
.map(Locale::forLanguageTag)
.collect(Collectors.toList());
if (!gotList.equals(expectedList)) {
throw new RuntimeException("\n" + gotList.toString() + "\n is not equal to \n" +
expectedList.toString());
}
}
}