7196799: CLDR adapter can not be invoked when region code is specified in Locale
authornaoto
Thu, 04 Oct 2012 10:04:56 -0700
changeset 14024 694c379c2958
parent 14023 58aabbd73a9b
child 14025 fbebe005a3ee
child 14026 ec2c0bbcb881
7196799: CLDR adapter can not be invoked when region code is specified in Locale 7197573: java/util/Locale/LocaleProviders.sh failed. Reviewed-by: okutsu
jdk/make/java/java/FILES_java.gmk
jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java
jdk/src/share/classes/sun/util/locale/provider/FallbackLocaleProviderAdapter.java
jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java
jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java
jdk/test/java/util/Locale/LocaleProviders.java
jdk/test/java/util/Locale/LocaleProviders.sh
--- a/jdk/make/java/java/FILES_java.gmk	Thu Oct 04 11:54:16 2012 +0100
+++ b/jdk/make/java/java/FILES_java.gmk	Thu Oct 04 10:04:56 2012 -0700
@@ -213,6 +213,7 @@
             sun/util/locale/provider/DateFormatSymbolsProviderImpl.java \
             sun/util/locale/provider/DecimalFormatSymbolsProviderImpl.java \
             sun/util/locale/provider/DictionaryBasedBreakIterator.java \
+            sun/util/locale/provider/FallbackLocaleProviderAdapter.java \
             sun/util/locale/provider/HostLocaleProviderAdapter.java \
             sun/util/locale/provider/HostLocaleProviderAdapterImpl.java \
             sun/util/locale/provider/JRELocaleConstants.java \
--- a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java	Thu Oct 04 11:54:16 2012 +0100
+++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java	Thu Oct 04 10:04:56 2012 -0700
@@ -137,7 +137,7 @@
 
     @Override
     public boolean isSupportedLocale(Locale locale) {
-        if (locale == Locale.ROOT) {
+        if (Locale.ROOT.equals(locale)) {
             return true;
         }
         String calendarType = null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/util/locale/provider/FallbackLocaleProviderAdapter.java	Thu Oct 04 10:04:56 2012 -0700
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+/**
+ * FallbackProviderAdapter implementation.
+ *
+ * @author Naoto Sato
+ */
+public class FallbackLocaleProviderAdapter extends JRELocaleProviderAdapter {
+
+    /**
+     * Returns the type of this LocaleProviderAdapter
+     */
+    @Override
+    public LocaleProviderAdapter.Type getAdapterType() {
+        return Type.FALLBACK;
+    }
+}
--- a/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java	Thu Oct 04 11:54:16 2012 +0100
+++ b/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java	Thu Oct 04 10:04:56 2012 -0700
@@ -71,7 +71,7 @@
      */
     @Override
     public LocaleProviderAdapter.Type getAdapterType() {
-        return LocaleProviderAdapter.Type.JRE;
+        return Type.JRE;
     }
 
     /**
--- a/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java	Thu Oct 04 11:54:16 2012 +0100
+++ b/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java	Thu Oct 04 10:04:56 2012 -0700
@@ -59,7 +59,8 @@
         JRE("sun.util.resources", "sun.text.resources"),
         CLDR("sun.util.resources.cldr", "sun.text.resources.cldr"),
         SPI,
-        HOST;
+        HOST,
+        FALLBACK("sun.util.resources", "sun.text.resources");
 
         private final String UTIL_RESOURCES_PACKAGE;
         private final String TEXT_RESOURCES_PACKAGE;
@@ -111,41 +112,49 @@
      */
     private static LocaleProviderAdapter hostLocaleProviderAdapter = null;
 
+    /**
+     * FALLBACK Locale Data Adapter instance. It's basically the same with JRE, but only kicks
+     * in for the root locale.
+     */
+    private static LocaleProviderAdapter fallbackLocaleProviderAdapter = null;
+
     static {
         String order = AccessController.doPrivileged(
                            new sun.security.action.GetPropertyAction("java.locale.providers"));
-                    // Override adapterPreference with the properties one
-                    if (order != null && order.length() != 0) {
-                        String[] types = order.split(",");
-                        List<Type> typeList = new ArrayList<>();
-                        for (String type : types) {
-                            try {
-                            Type aType = Type.valueOf(type.trim().toUpperCase(Locale.ROOT));
+        // Override adapterPreference with the properties one
+        if (order != null && order.length() != 0) {
+            String[] types = order.split(",");
+            List<Type> typeList = new ArrayList<>();
+            for (String type : types) {
+                try {
+                    Type aType = Type.valueOf(type.trim().toUpperCase(Locale.ROOT));
 
-                                // load adapter if necessary
-                                switch (aType) {
-                                case CLDR:
-                        cldrLocaleProviderAdapter = new CLDRLocaleProviderAdapter();
-                                    break;
-                                case HOST:
-                        hostLocaleProviderAdapter = new HostLocaleProviderAdapter();
-                                    break;
-                                }
-                                typeList.add(aType);
-                } catch (// could be caused by the user specifying wrong
-                                     // provider name or format in the system property
-                                     IllegalArgumentException |
-                                     UnsupportedOperationException e) {
-                                LocaleServiceProviderPool.config(LocaleProviderAdapter.class, e.toString());
-                            }
-                        }
+                    // load adapter if necessary
+                    switch (aType) {
+                        case CLDR:
+                            cldrLocaleProviderAdapter = new CLDRLocaleProviderAdapter();
+                            break;
+                        case HOST:
+                            hostLocaleProviderAdapter = new HostLocaleProviderAdapter();
+                            break;
+                    }
+                    typeList.add(aType);
+                } catch (IllegalArgumentException | UnsupportedOperationException e) {
+                    // could be caused by the user specifying wrong
+                    // provider name or format in the system property
+                    LocaleServiceProviderPool.config(LocaleProviderAdapter.class, e.toString());
+                }
+            }
 
-                        if (!typeList.contains(Type.JRE)) {
-                            // Append JRE as the last resort.
-                            typeList.add(Type.JRE);
-                        }
-                        adapterPreference = typeList.toArray(new Type[0]);
-                    }
+            if (!typeList.isEmpty()) {
+                if (!typeList.contains(Type.JRE)) {
+                    // Append FALLBACK as the last resort.
+                    fallbackLocaleProviderAdapter = new FallbackLocaleProviderAdapter();
+                    typeList.add(Type.FALLBACK);
+                }
+                adapterPreference = typeList.toArray(new Type[0]);
+            }
+        }
     }
 
 
@@ -162,6 +171,8 @@
             return spiLocaleProviderAdapter;
         case HOST:
             return hostLocaleProviderAdapter;
+        case FALLBACK:
+            return fallbackLocaleProviderAdapter;
         default:
             throw new InternalError("unknown locale data adapter type");
         }
@@ -173,7 +184,7 @@
 
     public static LocaleProviderAdapter getResourceBundleBased() {
         for (Type type : getAdapterPreference()) {
-            if (type == Type.JRE || type == Type.CLDR) {
+            if (type == Type.JRE || type == Type.CLDR || type == Type.FALLBACK) {
                 return forType(type);
             }
         }
@@ -218,8 +229,8 @@
             }
         }
 
-        // returns the adapter for JRE as the last resort
-        return jreLocaleProviderAdapter;
+        // returns the adapter for FALLBACK as the last resort
+        return fallbackLocaleProviderAdapter;
     }
 
     private static LocaleProviderAdapter findAdapter(Class<? extends LocaleServiceProvider> providerClass,
@@ -238,18 +249,24 @@
 
     /**
      * A utility method for implementing the default LocaleServiceProvider.isSupportedLocale
-     * for the JRE and CLDR adapters.
+     * for the JRE, CLDR, and FALLBACK adapters.
      */
     static boolean isSupportedLocale(Locale locale, LocaleProviderAdapter.Type type, Set<String> langtags) {
-        assert type == Type.JRE || type == Type.CLDR;
-        if (locale == Locale.ROOT) {
+        assert type == Type.JRE || type == Type.CLDR || type == Type.FALLBACK;
+        if (Locale.ROOT.equals(locale)) {
             return true;
         }
+
+        if (type == Type.FALLBACK) {
+            // no other locales except ROOT are supported for FALLBACK
+            return false;
+        }
+
         locale = locale.stripExtensions();
         if (langtags.contains(locale.toLanguageTag())) {
             return true;
         }
-        if (type == LocaleProviderAdapter.Type.JRE) {
+        if (type == Type.JRE) {
             String oldname = locale.toString().replace('_', '-');
             return langtags.contains(oldname);
         }
--- a/jdk/test/java/util/Locale/LocaleProviders.java	Thu Oct 04 11:54:16 2012 +0100
+++ b/jdk/test/java/util/Locale/LocaleProviders.java	Thu Oct 04 10:04:56 2012 -0700
@@ -27,14 +27,20 @@
 public class LocaleProviders {
 
     public static void main(String[] args) {
-        String expected = args[0];
-        Locale testLocale = new Locale(args[1], args[2]);
-        String preference = System.getProperty("java.locale.providers", "");
-        LocaleProviderAdapter lda = LocaleProviderAdapter.getAdapter(DateFormatProvider.class, testLocale);
-        LocaleProviderAdapter.Type type = lda.getAdapterType();
-        System.out.printf("testLocale: %s, got: %s, expected: %s\n", testLocale, type, expected);
-        if (!type.toString().equals(expected)) {
-            throw new RuntimeException("Returned locale data adapter is not correct.");
+        if (args.length == 0) {
+            // no args indicates that the caller is asking the platform default locale.
+            Locale defloc = Locale.getDefault();
+            System.out.printf("%s,%s\n", defloc.getLanguage(), defloc.getCountry());
+        } else {
+            String expected = args[0];
+            Locale testLocale = new Locale(args[1], (args.length >= 3 ? args[2] : ""));
+            String preference = System.getProperty("java.locale.providers", "");
+            LocaleProviderAdapter lda = LocaleProviderAdapter.getAdapter(DateFormatProvider.class, testLocale);
+            LocaleProviderAdapter.Type type = lda.getAdapterType();
+            System.out.printf("testLocale: %s, got: %s, expected: %s\n", testLocale, type, expected);
+            if (!type.toString().equals(expected)) {
+                throw new RuntimeException("Returned locale data adapter is not correct.");
+            }
         }
     }
 }
--- a/jdk/test/java/util/Locale/LocaleProviders.sh	Thu Oct 04 11:54:16 2012 +0100
+++ b/jdk/test/java/util/Locale/LocaleProviders.sh	Thu Oct 04 10:04:56 2012 -0700
@@ -23,7 +23,7 @@
 #!/bin/sh
 #
 # @test
-# @bug 6336885
+# @bug 6336885 7196799 7197573
 # @summary tests for "java.locale.providers" system property
 # @compile -XDignore.symbol.file LocaleProviders.java
 # @run shell/timeout=600 LocaleProviders.sh
@@ -65,9 +65,16 @@
     ;;
 esac
 
+# get the platform default locale
+PLATDEF=`${TESTJAVA}${FS}bin${FS}java -classpath ${TESTCLASSES} LocaleProviders`
+DEFLANG=`echo ${PLATDEF} | sed -e "s/,.*//"`
+DEFCTRY=`echo ${PLATDEF} | sed -e "s/.*,//"`
+echo "DEFLANG=${DEFLANG}"
+echo "DEFCTRY=${DEFCTRY}"
+
 runTest()
 {
-    RUNCMD="${TESTJAVA}${FS}bin${FS}java -classpath ${TESTCLASSES} -Duser.language=$DEFLANG -Duser.country=$DEFCTRY -Djava.locale.providers=$PREFLIST LocaleProviders $EXPECTED $TESTLANG $TESTCTRY"
+    RUNCMD="${TESTJAVA}${FS}bin${FS}java -classpath ${TESTCLASSES} -Djava.locale.providers=$PREFLIST LocaleProviders $EXPECTED $TESTLANG $TESTCTRY"
     echo ${RUNCMD}
     ${RUNCMD}
     result=$?
@@ -81,9 +88,7 @@
 }
 
 # testing HOST is selected for the default locale, if specified on Windows or MacOSX
-DEFLANG=en
-DEFCTRY=US
-PREFLIST=HOST
+PREFLIST=HOST,JRE
 case "$OS" in
   Windows_NT* )
     WINVER=`uname -r`
@@ -101,28 +106,32 @@
     EXPECTED=JRE
     ;;
 esac
-TESTLANG=en
-TESTCTRY=US
+TESTLANG=${DEFLANG}
+TESTCTRY=${DEFCTRY}
 runTest
 
 # testing HOST is NOT selected for the non-default locale, if specified
-DEFLANG=en
-DEFCTRY=US
-PREFLIST=HOST
+PREFLIST=HOST,JRE
 EXPECTED=JRE
-TESTLANG=en
-TESTCTRY=GB
+if [ "${DEFLANG}" = "en" ]
+then
+  TESTLANG=ja
+  TESTCTRY=JP
+else
+  TESTLANG=en
+  TESTCTRY=US
+fi
 runTest
 
 # testing SPI is NOT selected, as there is none.
-PREFLIST=SPI
+PREFLIST=SPI,JRE
 EXPECTED=JRE
 TESTLANG=en
 TESTCTRY=US
 runTest
 
 # testing the order, variaton #1. This assumes en_GB DateFormat data are available both in JRE & CLDR
-PREFLIST=CLDR
+PREFLIST=CLDR,JRE
 EXPECTED=CLDR
 TESTLANG=en
 TESTCTRY=GB
@@ -142,4 +151,28 @@
 TESTCTRY=GB
 runTest
 
+# testing the order, variaton #4 for the bug 7196799. CLDR's "zh" data should be used in "zh_CN"
+PREFLIST=CLDR
+EXPECTED=CLDR
+TESTLANG=zh
+TESTCTRY=CN
+runTest
+
+# testing FALLBACK provider. SPI and invalid one cases.
+PREFLIST=SPI
+EXPECTED=FALLBACK
+TESTLANG=en
+TESTCTRY=US
+runTest
+PREFLIST=FOO
+EXPECTED=JRE
+TESTLANG=en
+TESTCTRY=US
+runTest
+PREFLIST=BAR,SPI
+EXPECTED=FALLBACK
+TESTLANG=en
+TESTCTRY=US
+runTest
+
 exit $result