jdk/src/share/classes/java/util/Locale.java
changeset 6489 9e7015635425
parent 5506 202f599c92aa
child 6501 684810d882b3
--- a/jdk/src/share/classes/java/util/Locale.java	Mon Aug 23 14:14:52 2010 +0900
+++ b/jdk/src/share/classes/java/util/Locale.java	Tue Aug 31 11:27:10 2010 -0700
@@ -395,31 +395,103 @@
         // do not synchronize this method - see 4071298
         // it's OK if more than one default locale happens to be created
         if (defaultLocale == null) {
-            String language, region, country, variant;
+            initDefault();
+        }
+        return defaultLocale;
+    }
+
+    /**
+     * Gets the current value of the default locale for the specified Category
+     * for this instance of the Java Virtual Machine.
+     * <p>
+     * The Java Virtual Machine sets the default locale during startup based
+     * on the host environment. It is used by many locale-sensitive methods
+     * if no locale is explicitly specified. It can be changed using the
+     * setDefault(Locale.Category, Locale) method.
+     *
+     * @param category - the specified category to get the default locale
+     * @throws NullPointerException - if category is null
+     * @return the default locale for the specified Category for this instance
+     *     of the Java Virtual Machine
+     * @see #setDefault(Locale.Category, Locale)
+     * @since 1.7
+     */
+    public static Locale getDefault(Locale.Category category) {
+        // do not synchronize this method - see 4071298
+        // it's OK if more than one default locale happens to be created
+        switch (category) {
+        case DISPLAY:
+            if (defaultDisplayLocale == null) {
+                initDefault(category);
+            }
+            return defaultDisplayLocale;
+        case FORMAT:
+            if (defaultFormatLocale == null) {
+                initDefault(category);
+            }
+            return defaultFormatLocale;
+        default:
+            assert false: "Unknown Category";
+        }
+        return getDefault();
+    }
+
+    private static void initDefault() {
+        String language, region, country, variant;
+        language = AccessController.doPrivileged(
+            new GetPropertyAction("user.language", "en"));
+        // for compatibility, check for old user.region property
+        region = AccessController.doPrivileged(
+            new GetPropertyAction("user.region"));
+        if (region != null) {
+            // region can be of form country, country_variant, or _variant
+            int i = region.indexOf('_');
+            if (i >= 0) {
+                country = region.substring(0, i);
+                variant = region.substring(i + 1);
+            } else {
+                country = region;
+                variant = "";
+            }
+        } else {
+            country = AccessController.doPrivileged(
+                new GetPropertyAction("user.country", ""));
+            variant = AccessController.doPrivileged(
+                new GetPropertyAction("user.variant", ""));
+        }
+        defaultLocale = getInstance(language, country, variant);
+    }
+
+    private static void initDefault(Locale.Category category) {
+        String language, region, country, variant;
+        switch (category) {
+        case DISPLAY:
             language = AccessController.doPrivileged(
-                new GetPropertyAction("user.language", "en"));
-            // for compatibility, check for old user.region property
-            region = AccessController.doPrivileged(
-                new GetPropertyAction("user.region"));
-            if (region != null) {
-                // region can be of form country, country_variant, or _variant
-                int i = region.indexOf('_');
-                if (i >= 0) {
-                    country = region.substring(0, i);
-                    variant = region.substring(i + 1);
-                } else {
-                    country = region;
-                    variant = "";
-                }
+                new GetPropertyAction("user.language.display", ""));
+            if ("".equals(language)) {
+                defaultDisplayLocale = getDefault();
             } else {
                 country = AccessController.doPrivileged(
-                    new GetPropertyAction("user.country", ""));
+                    new GetPropertyAction("user.country.display", ""));
                 variant = AccessController.doPrivileged(
-                    new GetPropertyAction("user.variant", ""));
+                    new GetPropertyAction("user.variant.display", ""));
+                defaultDisplayLocale = getInstance(language, country, variant);
             }
-            defaultLocale = getInstance(language, country, variant);
+            break;
+        case FORMAT:
+            language = AccessController.doPrivileged(
+                new GetPropertyAction("user.language.format", ""));
+            if ("".equals(language)) {
+                defaultFormatLocale = getDefault();
+            } else {
+                country = AccessController.doPrivileged(
+                    new GetPropertyAction("user.country.format", ""));
+                variant = AccessController.doPrivileged(
+                    new GetPropertyAction("user.variant.format", ""));
+                defaultFormatLocale = getInstance(language, country, variant);
+            }
+            break;
         }
-        return defaultLocale;
     }
 
     /**
@@ -438,6 +510,9 @@
      * of functionality, this method should only be used if the caller
      * is prepared to reinitialize locale-sensitive code running
      * within the same Java Virtual Machine.
+     * <p>
+     * By setting the default locale with this method, all of the default
+     * locales for each Category are also set to the specified default locale.
      *
      * @throws SecurityException
      *        if a security manager exists and its
@@ -448,13 +523,59 @@
      * @see java.util.PropertyPermission
      */
     public static synchronized void setDefault(Locale newLocale) {
+        setDefault(Category.DISPLAY, newLocale);
+        setDefault(Category.FORMAT, newLocale);
+        defaultLocale = newLocale;
+    }
+
+    /**
+     * Sets the default locale for the specified Category for this instance
+     * of the Java Virtual Machine. This does not affect the host locale.
+     * <p>
+     * If there is a security manager, its checkPermission method is called
+     * with a PropertyPermission("user.language", "write") permission before
+     * the default locale is changed.
+     * <p>
+     * The Java Virtual Machine sets the default locale during startup based
+     * on the host environment. It is used by many locale-sensitive methods
+     * if no locale is explicitly specified.
+     * <p>
+     * Since changing the default locale may affect many different areas of
+     * functionality, this method should only be used if the caller is
+     * prepared to reinitialize locale-sensitive code running within the
+     * same Java Virtual Machine.
+     * <p>
+     *
+     * @param category - the specified category to set the default locale
+     * @param newLocale - the new default locale
+     * @throws SecurityException - if a security manager exists and its
+     *     checkPermission method doesn't allow the operation.
+     * @throws NullPointerException - if category and/or newLocale is null
+     * @see SecurityManager.checkPermission(java.security.Permission)
+     * @see PropertyPermission
+     * @see #getDefault(Locale.Category)
+     * @since 1.7
+     */
+    public static synchronized void setDefault(Locale.Category category,
+        Locale newLocale) {
+        if (category == null)
+            throw new NullPointerException("Category cannot be NULL");
         if (newLocale == null)
             throw new NullPointerException("Can't set default locale to NULL");
 
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) sm.checkPermission(new PropertyPermission
                         ("user.language", "write"));
-            defaultLocale = newLocale;
+        switch (category) {
+        case DISPLAY:
+            defaultDisplayLocale = newLocale;
+            break;
+        case FORMAT:
+            defaultFormatLocale = newLocale;
+            break;
+        default:
+            assert false: "Unknown Category";
+        }
     }
 
     /**
@@ -642,7 +763,7 @@
      * value.  If the locale doesn't specify a language, this function returns the empty string.
      */
     public final String getDisplayLanguage() {
-        return getDisplayLanguage(getDefault());
+        return getDisplayLanguage(getDefault(Category.DISPLAY));
     }
 
     /**
@@ -677,7 +798,7 @@
      * value.  If the locale doesn't specify a country, this function returns the empty string.
      */
     public final String getDisplayCountry() {
-        return getDisplayCountry(getDefault());
+        return getDisplayCountry(getDefault(Category.DISPLAY));
     }
 
     /**
@@ -744,7 +865,7 @@
      * doesn't specify a variant code, this function returns the empty string.
      */
     public final String getDisplayVariant() {
-        return getDisplayVariant(getDefault());
+        return getDisplayVariant(getDefault(Category.DISPLAY));
     }
 
     /**
@@ -790,7 +911,7 @@
      * and variant fields are all empty, this function returns the empty string.
      */
     public final String getDisplayName() {
-        return getDisplayName(getDefault());
+        return getDisplayName(getDefault(Category.DISPLAY));
     }
 
     /**
@@ -970,6 +1091,8 @@
     private transient volatile int hashCodeValue = 0;
 
     private static Locale defaultLocale = null;
+    private static Locale defaultDisplayLocale = null;
+    private static Locale defaultFormatLocale = null;
 
     /**
      * Return an array of the display names of the variant.
@@ -1140,4 +1263,28 @@
             return null;
         }
     }
+
+    /**
+     * Enum for locale categories.  These locale categories are used to get/set
+     * the default locale for the specific functionality represented by the
+     * category.
+     *
+     * @see #getDefault(Locale.Category)
+     * @see #setDefault(Locale.Category, Locale)
+     * @since 1.7
+     */
+    public enum Category {
+
+        /**
+         * Category used to represent the default locale for
+         * displaying user interfaces.
+         */
+        DISPLAY,
+
+        /**
+         * Category used to represent the default locale for
+         * formatting dates, numbers, and/or currencies.
+         */
+        FORMAT,
+    }
 }