author | naoto |
Tue, 02 Sep 2014 14:11:38 -0700 | |
changeset 26360 | 697f70835528 |
parent 26359 | 50d45d375866 |
child 26361 | 869d2905615d |
--- a/jdk/make/CreateJars.gmk Tue Sep 02 11:21:29 2014 -0700 +++ b/jdk/make/CreateJars.gmk Tue Sep 02 14:11:38 2014 -0700 @@ -76,13 +76,24 @@ 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 @@ 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 @@ 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))
--- a/jdk/make/gensrc/GensrcLocaleDataMetaInfo.gmk Tue Sep 02 11:21:29 2014 -0700 +++ b/jdk/make/gensrc/GensrcLocaleDataMetaInfo.gmk Tue Sep 02 14:11:38 2014 -0700 @@ -58,7 +58,14 @@ # 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 @@ 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 @@ #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 ################################################################################
--- a/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java Tue Sep 02 11:21:29 2014 -0700 +++ b/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java Tue Sep 02 14:11:38 2014 -0700 @@ -431,7 +431,7 @@ 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);
--- a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java Tue Sep 02 11:21:29 2014 -0700 +++ b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java Tue Sep 02 14:11:38 2014 -0700 @@ -159,8 +159,10 @@ 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 @@ 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}"); } }
--- a/jdk/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java Tue Sep 02 11:21:29 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java Tue Sep 02 14:11:38 2014 -0700 @@ -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 @@ * @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 @@ @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 @@ @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()) {
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java Tue Sep 02 11:21:29 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java Tue Sep 02 14:11:38 2014 -0700 @@ -56,7 +56,7 @@ /** * SPI implementations map */ - private ConcurrentMap<Class<? extends LocaleServiceProvider>, LocaleServiceProvider> providersMap = + private final ConcurrentMap<Class<? extends LocaleServiceProvider>, LocaleServiceProvider> providersMap = new ConcurrentHashMap<>(); /** @@ -167,7 +167,6 @@ avail.addAll(Arrays.asList(lsp.getAvailableLocales())); } } - availableLocales = avail.toArray(new Locale[0]); } // assuming caller won't mutate the array. @@ -178,7 +177,7 @@ * 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() {
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Tue Sep 02 11:21:29 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Tue Sep 02 14:11:38 2014 -0700 @@ -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.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 @@ */ 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 @@ } 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 @@ 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 @@ } 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; - } -}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template Tue Sep 02 11:21:29 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template Tue Sep 02 14:11:38 2014 -0700 @@ -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; - - -public class LocaleDataMetaInfo { +import java.util.Map; +import sun.util.locale.provider.LocaleDataMetaInfo; +import static sun.util.locale.provider.LocaleProviderAdapter.Type; - private static final HashMap<String, String> resourceNameToLocales = - new HashMap<String, String>(7); +public class #Lang#LocaleDataMetaInfo implements LocaleDataMetaInfo { + 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 @@ 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); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo.java Tue Sep 02 14:11:38 2014 -0700 @@ -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); +}
--- a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java Tue Sep 02 11:21:29 2014 -0700 +++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java Tue Sep 02 14:11:38 2014 -0700 @@ -50,7 +50,6 @@ 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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.localedata/META-INF/cldrdata-services/sun.util.locale.provider.LocaleDataMetaInfo Tue Sep 02 14:11:38 2014 -0700 @@ -0,0 +1,1 @@ +sun.util.cldr.CLDRLocaleDataMetaInfo
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.localedata/META-INF/localedata-services/sun.util.locale.provider.LocaleDataMetaInfo Tue Sep 02 14:11:38 2014 -0700 @@ -0,0 +1,1 @@ +sun.util.resources.provider.NonEnLocaleDataMetaInfo
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/util/locale/provider/Bug8038436.java Tue Sep 02 14:11:38 2014 -0700 @@ -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()); + } + } +}