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 } |