jdk/src/share/classes/java/util/Locale.java
changeset 13583 dc0017b1a452
parent 11282 2c8538c9daa6
child 14009 21856a20cc1d
equal deleted inserted replaced
13582:16f0af616ea0 13583:dc0017b1a452
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    48 import java.security.AccessController;
    48 import java.security.AccessController;
    49 import java.text.MessageFormat;
    49 import java.text.MessageFormat;
    50 import java.util.spi.LocaleNameProvider;
    50 import java.util.spi.LocaleNameProvider;
    51 
    51 
    52 import sun.security.action.GetPropertyAction;
    52 import sun.security.action.GetPropertyAction;
    53 import sun.util.LocaleServiceProviderPool;
    53 import sun.util.locale.provider.LocaleServiceProviderPool;
    54 import sun.util.locale.BaseLocale;
    54 import sun.util.locale.BaseLocale;
    55 import sun.util.locale.InternalLocaleBuilder;
    55 import sun.util.locale.InternalLocaleBuilder;
    56 import sun.util.locale.LanguageTag;
    56 import sun.util.locale.LanguageTag;
    57 import sun.util.locale.LocaleExtensions;
    57 import sun.util.locale.LocaleExtensions;
    58 import sun.util.locale.LocaleObjectCache;
    58 import sun.util.locale.LocaleObjectCache;
    59 import sun.util.locale.LocaleSyntaxException;
    59 import sun.util.locale.LocaleSyntaxException;
    60 import sun.util.locale.LocaleUtils;
    60 import sun.util.locale.LocaleUtils;
    61 import sun.util.locale.ParseStatus;
    61 import sun.util.locale.ParseStatus;
    62 import sun.util.locale.UnicodeLocaleExtension;
    62 import sun.util.locale.provider.LocaleProviderAdapter;
    63 import sun.util.resources.LocaleData;
       
    64 import sun.util.resources.OpenListResourceBundle;
    63 import sun.util.resources.OpenListResourceBundle;
    65 
    64 
    66 /**
    65 /**
    67  * A <code>Locale</code> object represents a specific geographical, political,
    66  * A <code>Locale</code> object represents a specific geographical, political,
    68  * or cultural region. An operation that requires a <code>Locale</code> to perform
    67  * or cultural region. An operation that requires a <code>Locale</code> to perform
   963         String[] result = new String[isoLanguages.length];
   962         String[] result = new String[isoLanguages.length];
   964         System.arraycopy(isoLanguages, 0, result, 0, isoLanguages.length);
   963         System.arraycopy(isoLanguages, 0, result, 0, isoLanguages.length);
   965         return result;
   964         return result;
   966     }
   965     }
   967 
   966 
   968     private static final String[] getISO2Table(String table) {
   967     private static String[] getISO2Table(String table) {
   969         int len = table.length() / 5;
   968         int len = table.length() / 5;
   970         String[] isoTable = new String[len];
   969         String[] isoTable = new String[len];
   971         for (int i = 0, j = 0; i < len; i++, j += 5) {
   970         for (int i = 0, j = 0; i < len; i++, j += 5) {
   972             isoTable[i] = table.substring(j, j + 2);
   971             isoTable[i] = table.substring(j, j + 2);
   973         }
   972         }
  1032     public String getVariant() {
  1031     public String getVariant() {
  1033         return baseLocale.getVariant();
  1032         return baseLocale.getVariant();
  1034     }
  1033     }
  1035 
  1034 
  1036     /**
  1035     /**
       
  1036      * Returns {@code true} if this {@code Locale} has any <a href="#def_extensions">
       
  1037      * extensions</a>.
       
  1038      *
       
  1039      * @return {@code true} if this {@code Locale} has any extensions
       
  1040      * @since 1.8
       
  1041      */
       
  1042     public boolean hasExtensions() {
       
  1043         return localeExtensions != null;
       
  1044     }
       
  1045 
       
  1046     /**
       
  1047      * Returns a copy of this {@code Locale} with no <a href="#def_extensions">
       
  1048      * extensions</a>. If this {@code Locale} has no extensions, this {@code Locale}
       
  1049      * is returned.
       
  1050      *
       
  1051      * @return a copy of this {@code Locale} with no extensions, or {@code this}
       
  1052      *         if {@code this} has no extensions
       
  1053      * @since 1.8
       
  1054      */
       
  1055     public Locale stripExtensions() {
       
  1056         return hasExtensions() ? Locale.getInstance(baseLocale, null) : this;
       
  1057     }
       
  1058 
       
  1059     /**
  1037      * Returns the extension (or private use) value associated with
  1060      * Returns the extension (or private use) value associated with
  1038      * the specified key, or null if there is no extension
  1061      * the specified key, or null if there is no extension
  1039      * associated with the key. To be well-formed, the key must be one
  1062      * associated with the key. To be well-formed, the key must be one
  1040      * of <code>[0-9A-Za-z]</code>. Keys are case-insensitive, so
  1063      * of <code>[0-9A-Za-z]</code>. Keys are case-insensitive, so
  1041      * for example 'z' and 'Z' represent the same extension.
  1064      * for example 'z' and 'Z' represent the same extension.
  1050      */
  1073      */
  1051     public String getExtension(char key) {
  1074     public String getExtension(char key) {
  1052         if (!LocaleExtensions.isValidKey(key)) {
  1075         if (!LocaleExtensions.isValidKey(key)) {
  1053             throw new IllegalArgumentException("Ill-formed extension key: " + key);
  1076             throw new IllegalArgumentException("Ill-formed extension key: " + key);
  1054         }
  1077         }
  1055         return (localeExtensions == null) ? null : localeExtensions.getExtensionValue(key);
  1078         return hasExtensions() ? localeExtensions.getExtensionValue(key) : null;
  1056     }
  1079     }
  1057 
  1080 
  1058     /**
  1081     /**
  1059      * Returns the set of extension keys associated with this locale, or the
  1082      * Returns the set of extension keys associated with this locale, or the
  1060      * empty set if it has no extensions. The returned set is unmodifiable.
  1083      * empty set if it has no extensions. The returned set is unmodifiable.
  1063      * @return The set of extension keys, or the empty set if this locale has
  1086      * @return The set of extension keys, or the empty set if this locale has
  1064      * no extensions.
  1087      * no extensions.
  1065      * @since 1.7
  1088      * @since 1.7
  1066      */
  1089      */
  1067     public Set<Character> getExtensionKeys() {
  1090     public Set<Character> getExtensionKeys() {
  1068         if (localeExtensions == null) {
  1091         if (!hasExtensions()) {
  1069             return Collections.emptySet();
  1092             return Collections.emptySet();
  1070         }
  1093         }
  1071         return localeExtensions.getKeys();
  1094         return localeExtensions.getKeys();
  1072     }
  1095     }
  1073 
  1096 
  1078      *
  1101      *
  1079      * @return The set of attributes.
  1102      * @return The set of attributes.
  1080      * @since 1.7
  1103      * @since 1.7
  1081      */
  1104      */
  1082     public Set<String> getUnicodeLocaleAttributes() {
  1105     public Set<String> getUnicodeLocaleAttributes() {
  1083         if (localeExtensions == null) {
  1106         if (!hasExtensions()) {
  1084             return Collections.emptySet();
  1107             return Collections.emptySet();
  1085         }
  1108         }
  1086         return localeExtensions.getUnicodeLocaleAttributes();
  1109         return localeExtensions.getUnicodeLocaleAttributes();
  1087     }
  1110     }
  1088 
  1111 
  1099      * @throws IllegalArgumentException if the key is not well-formed
  1122      * @throws IllegalArgumentException if the key is not well-formed
  1100      * @throws NullPointerException if <code>key</code> is null
  1123      * @throws NullPointerException if <code>key</code> is null
  1101      * @since 1.7
  1124      * @since 1.7
  1102      */
  1125      */
  1103     public String getUnicodeLocaleType(String key) {
  1126     public String getUnicodeLocaleType(String key) {
  1104         if (!UnicodeLocaleExtension.isKey(key)) {
  1127         if (!isUnicodeExtensionKey(key)) {
  1105             throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key);
  1128             throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key);
  1106         }
  1129         }
  1107         return (localeExtensions == null) ? null : localeExtensions.getUnicodeLocaleType(key);
  1130         return hasExtensions() ? localeExtensions.getUnicodeLocaleType(key) : null;
  1108     }
  1131     }
  1109 
  1132 
  1110     /**
  1133     /**
  1111      * Returns the set of Unicode locale keys defined by this locale, or the empty set if
  1134      * Returns the set of Unicode locale keys defined by this locale, or the empty set if
  1112      * this locale has none.  The returned set is immutable.  Keys are all lower case.
  1135      * this locale has none.  The returned set is immutable.  Keys are all lower case.
  1283      * @return a BCP47 language tag representing the locale
  1306      * @return a BCP47 language tag representing the locale
  1284      * @see #forLanguageTag(String)
  1307      * @see #forLanguageTag(String)
  1285      * @since 1.7
  1308      * @since 1.7
  1286      */
  1309      */
  1287     public String toLanguageTag() {
  1310     public String toLanguageTag() {
       
  1311         if (languageTag != null) {
       
  1312             return languageTag;
       
  1313         }
       
  1314 
  1288         LanguageTag tag = LanguageTag.parseLocale(baseLocale, localeExtensions);
  1315         LanguageTag tag = LanguageTag.parseLocale(baseLocale, localeExtensions);
  1289         StringBuilder buf = new StringBuilder();
  1316         StringBuilder buf = new StringBuilder();
  1290 
  1317 
  1291         String subtag = tag.getLanguage();
  1318         String subtag = tag.getLanguage();
  1292         if (subtag.length() > 0) {
  1319         if (subtag.length() > 0) {
  1326             buf.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP);
  1353             buf.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP);
  1327             // preserve casing
  1354             // preserve casing
  1328             buf.append(subtag);
  1355             buf.append(subtag);
  1329         }
  1356         }
  1330 
  1357 
  1331         return buf.toString();
  1358         String langTag = buf.toString();
       
  1359         synchronized (this) {
       
  1360             if (languageTag == null) {
       
  1361                 languageTag = langTag;
       
  1362             }
       
  1363         }
       
  1364         return languageTag;
  1332     }
  1365     }
  1333 
  1366 
  1334     /**
  1367     /**
  1335      * Returns a locale for the specified IETF BCP 47 language tag string.
  1368      * Returns a locale for the specified IETF BCP 47 language tag string.
  1336      *
  1369      *
  1512                     + baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
  1545                     + baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
  1513         }
  1546         }
  1514         return country3;
  1547         return country3;
  1515     }
  1548     }
  1516 
  1549 
  1517     private static final String getISO3Code(String iso2Code, String table) {
  1550     private static String getISO3Code(String iso2Code, String table) {
  1518         int codeLength = iso2Code.length();
  1551         int codeLength = iso2Code.length();
  1519         if (codeLength == 0) {
  1552         if (codeLength == 0) {
  1520             return "";
  1553             return "";
  1521         }
  1554         }
  1522 
  1555 
  1638 
  1671 
  1639         if (inLocale == null) {
  1672         if (inLocale == null) {
  1640             throw new NullPointerException();
  1673             throw new NullPointerException();
  1641         }
  1674         }
  1642 
  1675 
  1643         try {
  1676         LocaleServiceProviderPool pool =
  1644             OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
  1677             LocaleServiceProviderPool.getPool(LocaleNameProvider.class);
  1645             String key = (type == DISPLAY_VARIANT ? "%%"+code : code);
  1678         String key = (type == DISPLAY_VARIANT ? "%%"+code : code);
  1646             String result = null;
  1679         String result = pool.getLocalizedObject(
  1647 
  1680                                 LocaleNameGetter.INSTANCE,
  1648             // Check whether a provider can provide an implementation that's closer
  1681                                 inLocale, key, type, code);
  1649             // to the requested locale than what the Java runtime itself can provide.
       
  1650             LocaleServiceProviderPool pool =
       
  1651                 LocaleServiceProviderPool.getPool(LocaleNameProvider.class);
       
  1652             if (pool.hasProviders()) {
       
  1653                 result = pool.getLocalizedObject(
       
  1654                                     LocaleNameGetter.INSTANCE,
       
  1655                                     inLocale, bundle, key,
       
  1656                                     type, code);
       
  1657             }
       
  1658 
       
  1659             if (result == null) {
       
  1660                 result = bundle.getString(key);
       
  1661             }
       
  1662 
       
  1663             if (result != null) {
  1682             if (result != null) {
  1664                 return result;
  1683                 return result;
  1665             }
  1684             }
  1666         }
  1685 
  1667         catch (Exception e) {
       
  1668             // just fall through
       
  1669         }
       
  1670         return code;
  1686         return code;
  1671     }
  1687     }
  1672 
  1688 
  1673     /**
  1689     /**
  1674      * Returns a name for the locale's variant code that is appropriate for display to the
  1690      * Returns a name for the locale's variant code that is appropriate for display to the
  1688      */
  1704      */
  1689     public String getDisplayVariant(Locale inLocale) {
  1705     public String getDisplayVariant(Locale inLocale) {
  1690         if (baseLocale.getVariant().length() == 0)
  1706         if (baseLocale.getVariant().length() == 0)
  1691             return "";
  1707             return "";
  1692 
  1708 
  1693         OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
  1709         OpenListResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getLocaleNames(inLocale);
  1694 
  1710 
  1695         String names[] = getDisplayVariantArray(bundle, inLocale);
  1711         String names[] = getDisplayVariantArray(bundle, inLocale);
  1696 
  1712 
  1697         // Get the localized patterns for formatting a list, and use
  1713         // Get the localized patterns for formatting a list, and use
  1698         // them to format the list.
  1714         // them to format the list.
  1746      * this function returns the empty string.
  1762      * this function returns the empty string.
  1747      *
  1763      *
  1748      * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
  1764      * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
  1749      */
  1765      */
  1750     public String getDisplayName(Locale inLocale) {
  1766     public String getDisplayName(Locale inLocale) {
  1751         OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
  1767         OpenListResourceBundle bundle = LocaleProviderAdapter.forJRE().getLocaleData().getLocaleNames(inLocale);
  1752 
  1768 
  1753         String languageName = getDisplayLanguage(inLocale);
  1769         String languageName = getDisplayLanguage(inLocale);
  1754         String scriptName = getDisplayScript(inLocale);
  1770         String scriptName = getDisplayScript(inLocale);
  1755         String countryName = getDisplayCountry(inLocale);
  1771         String countryName = getDisplayCountry(inLocale);
  1756         String[] variantNames = getDisplayVariantArray(bundle, inLocale);
  1772         String[] variantNames = getDisplayVariantArray(bundle, inLocale);
  1792         }
  1808         }
  1793         if (countryName.length() != 0) {
  1809         if (countryName.length() != 0) {
  1794             names.add(countryName);
  1810             names.add(countryName);
  1795         }
  1811         }
  1796         if (variantNames.length != 0) {
  1812         if (variantNames.length != 0) {
  1797             for (String var : variantNames) {
  1813             names.addAll(Arrays.asList(variantNames));
  1798                 names.add(var);
       
  1799             }
       
  1800         }
  1814         }
  1801 
  1815 
  1802         // The first one in the main name
  1816         // The first one in the main name
  1803         mainName = names.get(0);
  1817         mainName = names.get(0);
  1804 
  1818 
  1841     }
  1855     }
  1842 
  1856 
  1843     /**
  1857     /**
  1844      * Overrides Cloneable.
  1858      * Overrides Cloneable.
  1845      */
  1859      */
       
  1860     @Override
  1846     public Object clone()
  1861     public Object clone()
  1847     {
  1862     {
  1848         try {
  1863         try {
  1849             Locale that = (Locale)super.clone();
  1864             Locale that = (Locale)super.clone();
  1850             return that;
  1865             return that;
  1908 
  1923 
  1909     private volatile static Locale defaultLocale = initDefault();
  1924     private volatile static Locale defaultLocale = initDefault();
  1910     private volatile static Locale defaultDisplayLocale = null;
  1925     private volatile static Locale defaultDisplayLocale = null;
  1911     private volatile static Locale defaultFormatLocale = null;
  1926     private volatile static Locale defaultFormatLocale = null;
  1912 
  1927 
       
  1928     private transient volatile String languageTag;
       
  1929 
  1913     /**
  1930     /**
  1914      * Return an array of the display names of the variant.
  1931      * Return an array of the display names of the variant.
  1915      * @param bundle the ResourceBundle to use to get the display names
  1932      * @param bundle the ResourceBundle to use to get the display names
  1916      * @return an array of display names, possible of zero length.
  1933      * @return an array of display names, possible of zero length.
  1917      */
  1934      */
  1943      */
  1960      */
  1944     private static String formatList(String[] stringList, String listPattern, String listCompositionPattern) {
  1961     private static String formatList(String[] stringList, String listPattern, String listCompositionPattern) {
  1945         // If we have no list patterns, compose the list in a simple,
  1962         // If we have no list patterns, compose the list in a simple,
  1946         // non-localized way.
  1963         // non-localized way.
  1947         if (listPattern == null || listCompositionPattern == null) {
  1964         if (listPattern == null || listCompositionPattern == null) {
  1948             StringBuffer result = new StringBuffer();
  1965             StringBuilder result = new StringBuilder();
  1949             for (int i=0; i<stringList.length; ++i) {
  1966             for (int i = 0; i < stringList.length; ++i) {
  1950                 if (i>0) result.append(',');
  1967                 if (i > 0) {
       
  1968                     result.append(',');
       
  1969                 }
  1951                 result.append(stringList[i]);
  1970                 result.append(stringList[i]);
  1952             }
  1971             }
  1953             return result.toString();
  1972             return result.toString();
  1954         }
  1973         }
  1955 
  1974 
  1990         System.arraycopy(list, 2, newList, 1, newList.length-1);
  2009         System.arraycopy(list, 2, newList, 1, newList.length-1);
  1991         newList[0] = newItem;
  2010         newList[0] = newItem;
  1992 
  2011 
  1993         // Recurse
  2012         // Recurse
  1994         return composeList(format, newList);
  2013         return composeList(format, newList);
       
  2014     }
       
  2015 
       
  2016     // Duplicate of sun.util.locale.UnicodeLocaleExtension.isKey in order to
       
  2017     // avoid its class loading.
       
  2018     private static boolean isUnicodeExtensionKey(String s) {
       
  2019         // 2alphanum
       
  2020         return (s.length() == 2) && LocaleUtils.isAlphaNumericString(s);
  1995     }
  2021     }
  1996 
  2022 
  1997     /**
  2023     /**
  1998      * @serialField language    String
  2024      * @serialField language    String
  1999      *      language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>)
  2025      *      language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>)
  2134      */
  2160      */
  2135     private static class LocaleNameGetter
  2161     private static class LocaleNameGetter
  2136         implements LocaleServiceProviderPool.LocalizedObjectGetter<LocaleNameProvider, String> {
  2162         implements LocaleServiceProviderPool.LocalizedObjectGetter<LocaleNameProvider, String> {
  2137         private static final LocaleNameGetter INSTANCE = new LocaleNameGetter();
  2163         private static final LocaleNameGetter INSTANCE = new LocaleNameGetter();
  2138 
  2164 
       
  2165         @Override
  2139         public String getObject(LocaleNameProvider localeNameProvider,
  2166         public String getObject(LocaleNameProvider localeNameProvider,
  2140                                 Locale locale,
  2167                                 Locale locale,
  2141                                 String key,
  2168                                 String key,
  2142                                 Object... params) {
  2169                                 Object... params) {
  2143             assert params.length == 2;
  2170             assert params.length == 2;