< prev index next >

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

Print this page
rev 54003 : [mq]: 8218948
   1 /*
   2  * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  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


  39  */
  40 
  41 package sun.util.locale.provider;
  42 
  43 import java.lang.ref.ReferenceQueue;
  44 import java.lang.ref.SoftReference;
  45 import java.text.MessageFormat;
  46 import java.text.NumberFormat;
  47 import java.util.Calendar;
  48 import java.util.HashSet;
  49 import java.util.LinkedHashSet;
  50 import java.util.Locale;
  51 import java.util.Map;
  52 import java.util.Objects;
  53 import java.util.ResourceBundle;
  54 import java.util.Set;
  55 import java.util.TimeZone;
  56 import java.util.concurrent.ConcurrentHashMap;
  57 import java.util.concurrent.ConcurrentMap;
  58 import sun.security.action.GetPropertyAction;
  59 import sun.util.calendar.ZoneInfo;
  60 import sun.util.resources.LocaleData;
  61 import sun.util.resources.OpenListResourceBundle;
  62 import sun.util.resources.ParallelListResourceBundle;
  63 import sun.util.resources.TimeZoneNamesBundle;
  64 
  65 /**
  66  * Central accessor to locale-dependent resources for JRE/CLDR provider adapters.
  67  *
  68  * @author Masayoshi Okutsu
  69  * @author Naoto Sato
  70  */
  71 public class LocaleResources {
  72 
  73     private final Locale locale;
  74     private final LocaleData localeData;
  75     private final LocaleProviderAdapter.Type type;
  76 
  77     // Resource cache
  78     private final ConcurrentMap<String, ResourceReference> cache = new ConcurrentHashMap<>();
  79     private final ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();


 254         OpenListResourceBundle olrb = localeData.getLocaleNames(locale);
 255 
 256         if (olrb.containsKey(key)) {
 257             localeName = olrb.getObject(key);
 258             cache.put(cacheKey,
 259                       new ResourceReference(cacheKey, localeName, referenceQueue));
 260         }
 261 
 262         return (String) localeName;
 263     }
 264 
 265     public Object getTimeZoneNames(String key) {
 266         Object val = null;
 267         String cacheKey = TIME_ZONE_NAMES + key;
 268 
 269         removeEmptyReferences();
 270         ResourceReference data = cache.get(cacheKey);
 271 
 272         if (Objects.isNull(data) || Objects.isNull(val = data.get())) {
 273             TimeZoneNamesBundle tznb = localeData.getTimeZoneNames(locale);
 274             if (tznb.containsKey(key)) {
 275                 if (key.startsWith(TZNB_EXCITY_PREFIX)) {

 276                     val = tznb.getString(key);
 277                     assert val instanceof String;
 278                     trace("tznb: %s key: %s, val: %s\n", tznb, key, val);





 279                 } else {
 280                     String[] names = tznb.getStringArray(key);







 281                     trace("tznb: %s key: %s, names: %s, %s, %s, %s, %s, %s, %s\n", tznb, key,
 282                         names[0], names[1], names[2], names[3], names[4], names[5], names[6]);
 283                     val = names;
 284                 }


 285                 cache.put(cacheKey,
 286                           new ResourceReference(cacheKey, val, referenceQueue));
 287             }
 288         }
 289 
 290         return val;
 291     }
 292 
 293     @SuppressWarnings("unchecked")
 294     Set<String> getZoneIDs() {
 295         Set<String> zoneIDs = null;
 296 
 297         removeEmptyReferences();
 298         ResourceReference data = cache.get(ZONE_IDS_CACHEKEY);
 299         if (data == null || ((zoneIDs = (Set<String>) data.get()) == null)) {
 300             TimeZoneNamesBundle rb = localeData.getTimeZoneNames(locale);
 301             zoneIDs = rb.keySet();
 302             cache.put(ZONE_IDS_CACHEKEY,
 303                       new ResourceReference(ZONE_IDS_CACHEKEY, (Object) zoneIDs, referenceQueue));
 304         }
 305 
 306         return zoneIDs;
 307     }
 308 
 309     // zoneStrings are cached separately in TimeZoneNameUtility.
 310     String[][] getZoneStrings() {
 311         TimeZoneNamesBundle rb = localeData.getTimeZoneNames(locale);
 312         Set<String> keyset = getZoneIDs();
 313         // Use a LinkedHashSet to preseve the order
 314         Set<String[]> value = new LinkedHashSet<>();
 315         Set<String> tzIds = new HashSet<>(Set.of(TimeZone.getAvailableIDs()));
 316         for (String key : keyset) {
 317             if (!key.startsWith(TZNB_EXCITY_PREFIX)) {
 318                 value.add(rb.getStringArray(key));
 319                 tzIds.remove(key);
 320             }
 321         }
 322 
 323         if (type == LocaleProviderAdapter.Type.CLDR) {
 324             // Add aliases data for CLDR
 325             Map<String, String> aliases = ZoneInfo.getAliasTable();
 326             // Note: TimeZoneNamesBundle creates a String[] on each getStringArray call.
 327 
 328             // Add timezones which are not present in this keyset,
 329             // so that their fallback names will be generated at runtime.
 330             tzIds.stream().filter(i -> (!i.startsWith("Etc/GMT")
 331                     && !i.startsWith("GMT")
 332                     && !i.startsWith("SystemV")))
 333                     .forEach(tzid -> {
 334                         String[] val = new String[7];
 335                         if (keyset.contains(tzid)) {
 336                             val = rb.getStringArray(tzid);
 337                         } else {
 338                             String tz = aliases.get(tzid);
 339                             if (keyset.contains(tz)) {
 340                                 val = rb.getStringArray(tz);

 341                             }
 342                         }
 343                         val[0] = tzid;
 344                         value.add(val);
 345                     });
 346         }
 347         return value.toArray(new String[0][]);
 348     }
 349 
 350     String[] getCalendarNames(String key) {
 351         String[] names = null;
 352         String cacheKey = CALENDAR_NAMES + key;
 353 
 354         removeEmptyReferences();
 355         ResourceReference data = cache.get(cacheKey);
 356 
 357         if (data == null || ((names = (String[]) data.get()) == null)) {
 358             ResourceBundle rb = localeData.getDateFormatData(locale);
 359             if (rb.containsKey(key)) {
 360                 names = rb.getStringArray(key);


   1 /*
   2  * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  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


  39  */
  40 
  41 package sun.util.locale.provider;
  42 
  43 import java.lang.ref.ReferenceQueue;
  44 import java.lang.ref.SoftReference;
  45 import java.text.MessageFormat;
  46 import java.text.NumberFormat;
  47 import java.util.Calendar;
  48 import java.util.HashSet;
  49 import java.util.LinkedHashSet;
  50 import java.util.Locale;
  51 import java.util.Map;
  52 import java.util.Objects;
  53 import java.util.ResourceBundle;
  54 import java.util.Set;
  55 import java.util.TimeZone;
  56 import java.util.concurrent.ConcurrentHashMap;
  57 import java.util.concurrent.ConcurrentMap;
  58 import sun.security.action.GetPropertyAction;

  59 import sun.util.resources.LocaleData;
  60 import sun.util.resources.OpenListResourceBundle;
  61 import sun.util.resources.ParallelListResourceBundle;
  62 import sun.util.resources.TimeZoneNamesBundle;
  63 
  64 /**
  65  * Central accessor to locale-dependent resources for JRE/CLDR provider adapters.
  66  *
  67  * @author Masayoshi Okutsu
  68  * @author Naoto Sato
  69  */
  70 public class LocaleResources {
  71 
  72     private final Locale locale;
  73     private final LocaleData localeData;
  74     private final LocaleProviderAdapter.Type type;
  75 
  76     // Resource cache
  77     private final ConcurrentMap<String, ResourceReference> cache = new ConcurrentHashMap<>();
  78     private final ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();


 253         OpenListResourceBundle olrb = localeData.getLocaleNames(locale);
 254 
 255         if (olrb.containsKey(key)) {
 256             localeName = olrb.getObject(key);
 257             cache.put(cacheKey,
 258                       new ResourceReference(cacheKey, localeName, referenceQueue));
 259         }
 260 
 261         return (String) localeName;
 262     }
 263 
 264     public Object getTimeZoneNames(String key) {
 265         Object val = null;
 266         String cacheKey = TIME_ZONE_NAMES + key;
 267 
 268         removeEmptyReferences();
 269         ResourceReference data = cache.get(cacheKey);
 270 
 271         if (Objects.isNull(data) || Objects.isNull(val = data.get())) {
 272             TimeZoneNamesBundle tznb = localeData.getTimeZoneNames(locale);

 273             if (key.startsWith(TZNB_EXCITY_PREFIX)) {
 274                 if (tznb.containsKey(key)) {
 275                     val = tznb.getString(key);
 276                     assert val instanceof String;
 277                     trace("tznb: %s key: %s, val: %s\n", tznb, key, val);
 278                 }
 279             } else {
 280                 String[] names = null;
 281                 if (tznb.containsKey(key)) {
 282                     names = tznb.getStringArray(key);
 283                 } else {
 284                     var tz = TimeZoneNameUtility.canonicalTZID(key).orElse(key);
 285                     if (tznb.containsKey(tz)) {
 286                         names = tznb.getStringArray(tz);
 287                     }
 288                 }
 289 
 290                 if (names != null) {
 291                     names[0] = key;
 292                     trace("tznb: %s key: %s, names: %s, %s, %s, %s, %s, %s, %s\n", tznb, key,
 293                         names[0], names[1], names[2], names[3], names[4], names[5], names[6]);
 294                     val = names;
 295                 }
 296             }
 297             if (val != null) {
 298                 cache.put(cacheKey,
 299                           new ResourceReference(cacheKey, val, referenceQueue));
 300             }
 301         }
 302 
 303         return val;
 304     }
 305 
 306     @SuppressWarnings("unchecked")
 307     Set<String> getZoneIDs() {
 308         Set<String> zoneIDs = null;
 309 
 310         removeEmptyReferences();
 311         ResourceReference data = cache.get(ZONE_IDS_CACHEKEY);
 312         if (data == null || ((zoneIDs = (Set<String>) data.get()) == null)) {
 313             TimeZoneNamesBundle rb = localeData.getTimeZoneNames(locale);
 314             zoneIDs = rb.keySet();
 315             cache.put(ZONE_IDS_CACHEKEY,
 316                       new ResourceReference(ZONE_IDS_CACHEKEY, (Object) zoneIDs, referenceQueue));
 317         }
 318 
 319         return zoneIDs;
 320     }
 321 
 322     // zoneStrings are cached separately in TimeZoneNameUtility.
 323     String[][] getZoneStrings() {
 324         TimeZoneNamesBundle rb = localeData.getTimeZoneNames(locale);
 325         Set<String> keyset = getZoneIDs();
 326         // Use a LinkedHashSet to preseve the order
 327         Set<String[]> value = new LinkedHashSet<>();
 328         Set<String> tzIds = new HashSet<>(Set.of(TimeZone.getAvailableIDs()));
 329         for (String key : keyset) {
 330             if (!key.startsWith(TZNB_EXCITY_PREFIX)) {
 331                 value.add(rb.getStringArray(key));
 332                 tzIds.remove(key);
 333             }
 334         }
 335 
 336         if (type == LocaleProviderAdapter.Type.CLDR) {


 337             // Note: TimeZoneNamesBundle creates a String[] on each getStringArray call.
 338 
 339             // Add timezones which are not present in this keyset,
 340             // so that their fallback names will be generated at runtime.
 341             tzIds.stream().filter(i -> (!i.startsWith("Etc/GMT")
 342                     && !i.startsWith("GMT")
 343                     && !i.startsWith("SystemV")))
 344                     .forEach(tzid -> {
 345                         String[] val = new String[7];
 346                         if (keyset.contains(tzid)) {
 347                             val = rb.getStringArray(tzid);
 348                         } else {
 349                             var canonID = TimeZoneNameUtility.canonicalTZID(tzid)
 350                                             .orElse(tzid);
 351                             if (keyset.contains(canonID)) {
 352                                 val = rb.getStringArray(canonID);
 353                             }
 354                         }
 355                         val[0] = tzid;
 356                         value.add(val);
 357                     });
 358         }
 359         return value.toArray(new String[0][]);
 360     }
 361 
 362     String[] getCalendarNames(String key) {
 363         String[] names = null;
 364         String cacheKey = CALENDAR_NAMES + key;
 365 
 366         removeEmptyReferences();
 367         ResourceReference data = cache.get(cacheKey);
 368 
 369         if (data == null || ((names = (String[]) data.get()) == null)) {
 370             ResourceBundle rb = localeData.getDateFormatData(locale);
 371             if (rb.containsKey(key)) {
 372                 names = rb.getStringArray(key);


< prev index next >