src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java

Print this page




  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.util.locale.provider;
  27 
  28 import java.security.AccessController;
  29 import java.security.PrivilegedAction;
  30 import java.security.PrivilegedExceptionAction;
  31 import java.text.spi.BreakIteratorProvider;
  32 import java.text.spi.CollatorProvider;
  33 import java.text.spi.DateFormatProvider;
  34 import java.text.spi.DateFormatSymbolsProvider;
  35 import java.text.spi.DecimalFormatSymbolsProvider;
  36 import java.text.spi.NumberFormatProvider;
  37 import java.util.Collections;
  38 import java.util.HashSet;

  39 import java.util.Locale;

  40 import java.util.ServiceLoader;
  41 import java.util.Set;
  42 import java.util.StringTokenizer;
  43 import java.util.concurrent.ConcurrentHashMap;
  44 import java.util.concurrent.ConcurrentMap;
  45 import java.util.spi.CalendarDataProvider;
  46 import java.util.spi.CalendarNameProvider;
  47 import java.util.spi.CurrencyNameProvider;
  48 import java.util.spi.LocaleNameProvider;
  49 import java.util.spi.LocaleServiceProvider;
  50 import java.util.spi.TimeZoneNameProvider;
  51 import sun.util.resources.LocaleData;
  52 import sun.util.spi.CalendarProvider;
  53 
  54 /**
  55  * LocaleProviderAdapter implementation for the legacy JRE locale data.
  56  *
  57  * @author Naoto Sato
  58  * @author Masayoshi Okutsu
  59  */


 362                 lr = lrc;
 363             }
 364         }
 365         return lr;
 366     }
 367 
 368     // ResourceBundleBasedAdapter method implementation
 369 
 370     @Override
 371     public LocaleData getLocaleData() {
 372         if (localeData == null) {
 373             synchronized (this) {
 374                 if (localeData == null) {
 375                     localeData = new LocaleData(getAdapterType());
 376                 }
 377             }
 378         }
 379         return localeData;
 380     }
 381 







 382     /**
 383      * Returns a list of the installed locales. Currently, this simply returns
 384      * the list of locales for which a sun.text.resources.FormatData bundle
 385      * exists. This bundle family happens to be the one with the broadest
 386      * locale coverage in the JRE.
 387      */
 388     @Override
 389     public Locale[] getAvailableLocales() {
 390         return AvailableJRELocales.localeList.clone();
 391     }
 392 
 393     public Set<String> getLanguageTagSet(String category) {
 394         Set<String> tagset = langtagSets.get(category);
 395         if (tagset == null) {
 396             tagset = createLanguageTagSet(category);
 397             Set<String> ts = langtagSets.putIfAbsent(category, tagset);
 398             if (ts != null) {
 399                 tagset = ts;
 400             }
 401         }
 402         return tagset;
 403     }
 404 
 405     protected Set<String> createLanguageTagSet(String category) {
 406         String supportedLocaleString = createSupportedLocaleString(category);
 407         if (supportedLocaleString == null) {
 408             return Collections.emptySet();
 409         }
 410         Set<String> tagset = new HashSet<>();
 411         StringTokenizer tokens = new StringTokenizer(supportedLocaleString);
 412         while (tokens.hasMoreTokens()) {
 413             tagset.add(tokens.nextToken());
 414         }
 415 
 416         return tagset;
 417     }
 418 
 419     private static String createSupportedLocaleString(String category) {
 420         // Directly call English tags, as we know it's in the base module.
 421         String supportedLocaleString = EnLocaleDataMetaInfo.getSupportedLocaleString(category);
 422 
 423         // Use ServiceLoader to dynamically acquire installed locales' tags.
 424         try {
 425             String nonENTags = AccessController.doPrivileged(new PrivilegedExceptionAction<String>() {
 426                 @Override
 427                 public String run() {
 428                     String tags = null;
 429                     for (LocaleDataMetaInfo ldmi :
 430                          ServiceLoader.loadInstalled(LocaleDataMetaInfo.class)) {
 431                         if (ldmi.getType() == LocaleProviderAdapter.Type.JRE) {
 432                             String t = ldmi.availableLanguageTags(category);
 433                             if (t != null) {
 434                                 if (tags == null) {
 435                                     tags = t;
 436                                 } else {
 437                                     tags += " " + t;
 438                                 }
 439                             }
 440                         }
 441                     }
 442                     return tags;
 443                 }
 444             });
 445 
 446             if (nonENTags != null) {
 447                 supportedLocaleString += " " + nonENTags;
 448             }
 449         }  catch (Exception e) {
 450             // catch any exception, and ignore them as if non-EN locales do not exist.
 451         }
 452 
 453         return supportedLocaleString;
 454     }
 455 
 456     /**
 457      * Lazy load available locales.
 458      */
 459     private static class AvailableJRELocales {
 460         private static final Locale[] localeList = createAvailableLocales();
 461         private AvailableJRELocales() {
 462         }
 463     }
 464 
 465     private static Locale[] createAvailableLocales() {
 466         /*
 467          * Gets the locale string list from LocaleDataMetaInfo classes and then


 480         Locale[] locales = new Locale[length + 1];
 481         locales[0] = Locale.ROOT;
 482         for (int i = 1; i <= length; i++) {
 483             String currentToken = localeStringTokenizer.nextToken();
 484             switch (currentToken) {
 485                 case "ja-JP-JP":
 486                     locales[i] = JRELocaleConstants.JA_JP_JP;
 487                     break;
 488                 case "no-NO-NY":
 489                     locales[i] = JRELocaleConstants.NO_NO_NY;
 490                     break;
 491                 case "th-TH-TH":
 492                     locales[i] = JRELocaleConstants.TH_TH_TH;
 493                     break;
 494                 default:
 495                     locales[i] = Locale.forLanguageTag(currentToken);
 496             }
 497         }
 498         return locales;
 499     }


















 500 }


  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.util.locale.provider;
  27 
  28 import java.security.AccessController;
  29 import java.security.PrivilegedAction;
  30 import java.security.PrivilegedExceptionAction;
  31 import java.text.spi.BreakIteratorProvider;
  32 import java.text.spi.CollatorProvider;
  33 import java.text.spi.DateFormatProvider;
  34 import java.text.spi.DateFormatSymbolsProvider;
  35 import java.text.spi.DecimalFormatSymbolsProvider;
  36 import java.text.spi.NumberFormatProvider;
  37 import java.util.Collections;
  38 import java.util.HashSet;
  39 import java.util.List;
  40 import java.util.Locale;
  41 import java.util.ResourceBundle;
  42 import java.util.ServiceLoader;
  43 import java.util.Set;
  44 import java.util.StringTokenizer;
  45 import java.util.concurrent.ConcurrentHashMap;
  46 import java.util.concurrent.ConcurrentMap;
  47 import java.util.spi.CalendarDataProvider;
  48 import java.util.spi.CalendarNameProvider;
  49 import java.util.spi.CurrencyNameProvider;
  50 import java.util.spi.LocaleNameProvider;
  51 import java.util.spi.LocaleServiceProvider;
  52 import java.util.spi.TimeZoneNameProvider;
  53 import sun.util.resources.LocaleData;
  54 import sun.util.spi.CalendarProvider;
  55 
  56 /**
  57  * LocaleProviderAdapter implementation for the legacy JRE locale data.
  58  *
  59  * @author Naoto Sato
  60  * @author Masayoshi Okutsu
  61  */


 364                 lr = lrc;
 365             }
 366         }
 367         return lr;
 368     }
 369 
 370     // ResourceBundleBasedAdapter method implementation
 371 
 372     @Override
 373     public LocaleData getLocaleData() {
 374         if (localeData == null) {
 375             synchronized (this) {
 376                 if (localeData == null) {
 377                     localeData = new LocaleData(getAdapterType());
 378                 }
 379             }
 380         }
 381         return localeData;
 382     }
 383 
 384     @Override
 385     public List<Locale> getCandidateLocales(String baseName, Locale locale) {
 386         return ResourceBundle.Control
 387             .getNoFallbackControl(ResourceBundle.Control.FORMAT_DEFAULT)
 388             .getCandidateLocales(baseName, locale);
 389     }
 390 
 391     /**
 392      * Returns a list of the installed locales. Currently, this simply returns
 393      * the list of locales for which a sun.text.resources.FormatData bundle
 394      * exists. This bundle family happens to be the one with the broadest
 395      * locale coverage in the JRE.
 396      */
 397     @Override
 398     public Locale[] getAvailableLocales() {
 399         return AvailableJRELocales.localeList.clone();
 400     }
 401 
 402     public Set<String> getLanguageTagSet(String category) {
 403         Set<String> tagset = langtagSets.get(category);
 404         if (tagset == null) {
 405             tagset = createLanguageTagSet(category);
 406             Set<String> ts = langtagSets.putIfAbsent(category, tagset);
 407             if (ts != null) {
 408                 tagset = ts;
 409             }
 410         }
 411         return tagset;
 412     }
 413 
 414     protected Set<String> createLanguageTagSet(String category) {
 415         String supportedLocaleString = createSupportedLocaleString(category);
 416         if (supportedLocaleString == null) {
 417             return Collections.emptySet();
 418         }
 419         Set<String> tagset = new HashSet<>();
 420         StringTokenizer tokens = new StringTokenizer(supportedLocaleString);
 421         while (tokens.hasMoreTokens()) {
 422             tagset.add(tokens.nextToken());
 423         }
 424 
 425         return tagset;
 426     }
 427 
 428     private static String createSupportedLocaleString(String category) {
 429         // Directly call Base tags, as we know it's in the base module.
 430         String supportedLocaleString = BaseLocaleDataMetaInfo.getSupportedLocaleString(category);
 431 
 432         // Use ServiceLoader to dynamically acquire installed locales' tags.
 433         try {
 434             String nonBaseTags = AccessController.doPrivileged(new PrivilegedExceptionAction<String>() {
 435                 @Override
 436                 public String run() {
 437                     String tags = null;
 438                     for (LocaleDataMetaInfo ldmi :
 439                          ServiceLoader.loadInstalled(LocaleDataMetaInfo.class)) {
 440                         if (ldmi.getType() == LocaleProviderAdapter.Type.JRE) {
 441                             String t = ldmi.availableLanguageTags(category);
 442                             if (t != null) {
 443                                 if (tags == null) {
 444                                     tags = t;
 445                                 } else {
 446                                     tags += " " + t;
 447                                 }
 448                             }
 449                         }
 450                     }
 451                     return tags;
 452                 }
 453             });
 454 
 455             if (nonBaseTags != null) {
 456                 supportedLocaleString += " " + nonBaseTags;
 457             }
 458         }  catch (Exception e) {
 459             // catch any exception, and ignore them as if non-EN locales do not exist.
 460         }
 461 
 462         return supportedLocaleString;
 463     }
 464 
 465     /**
 466      * Lazy load available locales.
 467      */
 468     private static class AvailableJRELocales {
 469         private static final Locale[] localeList = createAvailableLocales();
 470         private AvailableJRELocales() {
 471         }
 472     }
 473 
 474     private static Locale[] createAvailableLocales() {
 475         /*
 476          * Gets the locale string list from LocaleDataMetaInfo classes and then


 489         Locale[] locales = new Locale[length + 1];
 490         locales[0] = Locale.ROOT;
 491         for (int i = 1; i <= length; i++) {
 492             String currentToken = localeStringTokenizer.nextToken();
 493             switch (currentToken) {
 494                 case "ja-JP-JP":
 495                     locales[i] = JRELocaleConstants.JA_JP_JP;
 496                     break;
 497                 case "no-NO-NY":
 498                     locales[i] = JRELocaleConstants.NO_NO_NY;
 499                     break;
 500                 case "th-TH-TH":
 501                     locales[i] = JRELocaleConstants.TH_TH_TH;
 502                     break;
 503                 default:
 504                     locales[i] = Locale.forLanguageTag(currentToken);
 505             }
 506         }
 507         return locales;
 508     }
 509 
 510     @Override
 511     public boolean isSupportedProviderLocale(Locale locale,  Set<String> langtags) {
 512         if (Locale.ROOT.equals(locale)) {
 513             return true;
 514         }
 515 
 516         locale = locale.stripExtensions();
 517         if (langtags.contains(locale.toLanguageTag())) {
 518             return true;
 519         }
 520 
 521         String oldname = locale.toString().replace('_', '-');
 522         return langtags.contains(oldname) ||
 523                    "ja-JP-JP".equals(oldname) ||
 524                    "th-TH-TH".equals(oldname) ||
 525                    "no-NO-NY".equals(oldname);
 526     }
 527 }