Print this page
rev 5615 : 6336885: RFE: Locale Data Deployment Enhancements
4609153: Provide locale data for Indic locales
5104387: Support for gl_ES locale (galician language)
6337471: desktop/system locale preferences support
7056139: (cal) SPI support for locale-dependent Calendar parameters
7058206: Provide CalendarData SPI for week params and display field value names
7073852: Support multiple scripts for digits and decimal symbols per locale
7079560: [Fmt-Da] Context dependent month names support in SimpleDateFormat
7171324: getAvailableLocales() of locale sensitive services should return the actual availability of locales
7151414: (cal) Support calendar type identification
7168528: LocaleServiceProvider needs to be aware of Locale extensions
7171372: (cal) locale's default Calendar should be created if unknown calendar is specified
Summary: JEP 127: Improve Locale Data Packaging and Adopt Unicode CLDR Data (part 1 w/o Jigsaw. by Naoto Sato and Masayoshi Okutsu)

Split Close
Expand all
Collapse all
          --- old/src/share/classes/java/text/DateFormatSymbols.java
          +++ new/src/share/classes/java/text/DateFormatSymbols.java
   1    1  /*
   2      - * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
        2 + * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
   3    3   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4    4   *
   5    5   * This code is free software; you can redistribute it and/or modify it
   6    6   * under the terms of the GNU General Public License version 2 only, as
   7    7   * published by the Free Software Foundation.  Oracle designates this
   8    8   * particular file as subject to the "Classpath" exception as provided
   9    9   * by Oracle in the LICENSE file that accompanied this code.
  10   10   *
  11   11   * This code is distributed in the hope that it will be useful, but WITHOUT
  12   12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
↓ open down ↓ 24 lines elided ↑ open up ↑
  37   37   */
  38   38  
  39   39  package java.text;
  40   40  
  41   41  import java.io.IOException;
  42   42  import java.io.ObjectOutputStream;
  43   43  import java.io.Serializable;
  44   44  import java.lang.ref.SoftReference;
  45   45  import java.text.spi.DateFormatSymbolsProvider;
  46   46  import java.util.Arrays;
  47      -import java.util.List;
  48   47  import java.util.Locale;
  49   48  import java.util.ResourceBundle;
  50   49  import java.util.TimeZone;
  51   50  import java.util.concurrent.ConcurrentHashMap;
  52   51  import java.util.concurrent.ConcurrentMap;
  53      -import java.util.spi.LocaleServiceProvider;
  54      -import sun.util.LocaleServiceProviderPool;
  55      -import sun.util.TimeZoneNameUtility;
  56      -import sun.util.calendar.ZoneInfo;
       52 +import sun.util.locale.provider.LocaleProviderAdapter;
       53 +import sun.util.locale.provider.LocaleServiceProviderPool;
       54 +import sun.util.locale.provider.TimeZoneNameUtility;
  57   55  import sun.util.resources.LocaleData;
  58   56  
  59   57  /**
  60   58   * <code>DateFormatSymbols</code> is a public class for encapsulating
  61   59   * localizable date-time formatting data, such as the names of the
  62   60   * months, the names of the days of the week, and the time zone data.
  63   61   * <code>DateFormat</code> and <code>SimpleDateFormat</code> both use
  64   62   * <code>DateFormatSymbols</code> to encapsulate this information.
  65   63   *
  66   64   * <p>
↓ open down ↓ 153 lines elided ↑ open up ↑
 220  218  
 221  219      /**
 222  220       * Indicates that zoneStrings is set externally with setZoneStrings() method.
 223  221       */
 224  222      transient boolean isZoneStringsSet = false;
 225  223  
 226  224      /**
 227  225       * Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
 228  226       * All locales use the same these unlocalized pattern characters.
 229  227       */
 230      -    static final String  patternChars = "GyMdkHmsSEDFwWahKzZYuX";
      228 +    static final String  patternChars = "GyMdkHmsSEDFwWahKzZYuXL";
 231  229  
 232  230      static final int PATTERN_ERA                  =  0; // G
 233  231      static final int PATTERN_YEAR                 =  1; // y
 234  232      static final int PATTERN_MONTH                =  2; // M
 235  233      static final int PATTERN_DAY_OF_MONTH         =  3; // d
 236  234      static final int PATTERN_HOUR_OF_DAY1         =  4; // k
 237  235      static final int PATTERN_HOUR_OF_DAY0         =  5; // H
 238  236      static final int PATTERN_MINUTE               =  6; // m
 239  237      static final int PATTERN_SECOND               =  7; // s
 240  238      static final int PATTERN_MILLISECOND          =  8; // S
↓ open down ↓ 3 lines elided ↑ open up ↑
 244  242      static final int PATTERN_WEEK_OF_YEAR         = 12; // w
 245  243      static final int PATTERN_WEEK_OF_MONTH        = 13; // W
 246  244      static final int PATTERN_AM_PM                = 14; // a
 247  245      static final int PATTERN_HOUR1                = 15; // h
 248  246      static final int PATTERN_HOUR0                = 16; // K
 249  247      static final int PATTERN_ZONE_NAME            = 17; // z
 250  248      static final int PATTERN_ZONE_VALUE           = 18; // Z
 251  249      static final int PATTERN_WEEK_YEAR            = 19; // Y
 252  250      static final int PATTERN_ISO_DAY_OF_WEEK      = 20; // u
 253  251      static final int PATTERN_ISO_ZONE             = 21; // X
      252 +    static final int PATTERN_MONTH_STANDALONE     = 22; // L
 254  253  
 255  254      /**
 256  255       * Localized date-time pattern characters. For example, a locale may
 257  256       * wish to use 'u' rather than 'y' to represent years in its date format
 258  257       * pattern strings.
 259  258       * This string must be exactly 18 characters long, with the index of
 260  259       * the characters described by <code>DateFormat.ERA_FIELD</code>,
 261  260       * <code>DateFormat.YEAR_FIELD</code>, etc.  Thus, if the string were
 262  261       * "Xz...", then localized patterns would use 'X' for era and 'z' for year.
 263  262       * @serial
↓ open down ↓ 55 lines elided ↑ open up ↑
 319  318       * @param locale the given locale.
 320  319       * @return a <code>DateFormatSymbols</code> instance.
 321  320       * @exception NullPointerException if <code>locale</code> is null
 322  321       * @since 1.6
 323  322       */
 324  323      public static final DateFormatSymbols getInstance(Locale locale) {
 325  324          DateFormatSymbols dfs = getProviderInstance(locale);
 326  325          if (dfs != null) {
 327  326              return dfs;
 328  327          }
 329      -        return (DateFormatSymbols) getCachedInstance(locale).clone();
      328 +        throw new RuntimeException("DateFormatSymbols instance creation failed.");
 330  329      }
 331  330  
 332  331      /**
 333  332       * Returns a DateFormatSymbols provided by a provider or found in
 334  333       * the cache. Note that this method returns a cached instance,
 335  334       * not its clone. Therefore, the instance should never be given to
 336  335       * an application.
 337  336       */
 338  337      static final DateFormatSymbols getInstanceRef(Locale locale) {
 339  338          DateFormatSymbols dfs = getProviderInstance(locale);
 340  339          if (dfs != null) {
 341  340              return dfs;
 342  341          }
 343      -        return getCachedInstance(locale);
      342 +        throw new RuntimeException("DateFormatSymbols instance creation failed.");
 344  343      }
 345  344  
 346  345      private static DateFormatSymbols getProviderInstance(Locale locale) {
 347      -        DateFormatSymbols providersInstance = null;
 348      -
 349      -        // Check whether a provider can provide an implementation that's closer
 350      -        // to the requested locale than what the Java runtime itself can provide.
 351      -        LocaleServiceProviderPool pool =
 352      -            LocaleServiceProviderPool.getPool(DateFormatSymbolsProvider.class);
 353      -        if (pool.hasProviders()) {
 354      -            providersInstance = pool.getLocalizedObject(
 355      -                                    DateFormatSymbolsGetter.INSTANCE, locale);
 356      -        }
 357      -        return providersInstance;
      346 +        LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
      347 +        DateFormatSymbolsProvider provider = adapter.getDateFormatSymbolsProvider();
      348 +        return provider.getInstance(locale);
 358  349      }
 359  350  
 360  351      /**
 361      -     * Returns a cached DateFormatSymbols if it's found in the
 362      -     * cache. Otherwise, this method returns a newly cached instance
 363      -     * for the given locale.
 364      -     */
 365      -    private static DateFormatSymbols getCachedInstance(Locale locale) {
 366      -        SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
 367      -        DateFormatSymbols dfs = null;
 368      -        if (ref == null || (dfs = ref.get()) == null) {
 369      -            dfs = new DateFormatSymbols(locale);
 370      -            ref = new SoftReference<DateFormatSymbols>(dfs);
 371      -            SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
 372      -            if (x != null) {
 373      -                DateFormatSymbols y = x.get();
 374      -                if (y != null) {
 375      -                    dfs = y;
 376      -                } else {
 377      -                    // Replace the empty SoftReference with ref.
 378      -                    cachedInstances.put(locale, ref);
 379      -                }
 380      -            }
 381      -        }
 382      -        return dfs;
 383      -    }
 384      -
 385      -    /**
 386  352       * Gets era strings. For example: "AD" and "BC".
 387  353       * @return the era strings.
 388  354       */
 389  355      public String[] getEras() {
 390  356          return Arrays.copyOf(eras, eras.length);
 391  357      }
 392  358  
 393  359      /**
 394  360       * Sets era strings. For example: "AD" and "BC".
 395  361       * @param newEras the new era strings.
 396  362       */
 397  363      public void setEras(String[] newEras) {
 398  364          eras = Arrays.copyOf(newEras, newEras.length);
 399  365      }
 400  366  
 401  367      /**
 402  368       * Gets month strings. For example: "January", "February", etc.
      369 +     *
      370 +     * <p>If the language requires different forms for formatting and
      371 +     * stand-alone usages, this method returns month names in the
      372 +     * formatting form. For example, the preferred month name for
      373 +     * January in the Czech language is <em>ledna</em> in the
      374 +     * formatting form, while it is <em>leden</em> in the stand-alone
      375 +     * form. This method returns {@code "ledna"} in this case. Refer
      376 +     * to the <a href="http://unicode.org/reports/tr35/#Calendar_Elements">
      377 +     * Calendar Elements in the Unicode Locale Data Markup Language
      378 +     * (LDML) specification</a> for more details.
      379 +     *
 403  380       * @return the month strings.
 404  381       */
 405  382      public String[] getMonths() {
 406  383          return Arrays.copyOf(months, months.length);
 407  384      }
 408  385  
 409  386      /**
 410  387       * Sets month strings. For example: "January", "February", etc.
 411  388       * @param newMonths the new month strings.
 412  389       */
 413  390      public void setMonths(String[] newMonths) {
 414  391          months = Arrays.copyOf(newMonths, newMonths.length);
 415  392      }
 416  393  
 417  394      /**
 418  395       * Gets short month strings. For example: "Jan", "Feb", etc.
      396 +     *
      397 +     * <p>If the language requires different forms for formatting and
      398 +     * stand-alone usages, This method returns short month names in
      399 +     * the formatting form. For example, the preferred abbreviation
      400 +     * for January in the Catalan language is <em>de gen.</em> in the
      401 +     * formatting form, while it is <em>gen.</em> in the stand-alone
      402 +     * form. This method returns {@code "de gen."} in this case. Refer
      403 +     * to the <a href="http://unicode.org/reports/tr35/#Calendar_Elements">
      404 +     * Calendar Elements in the Unicode Locale Data Markup Language
      405 +     * (LDML) specification</a> for more details.
      406 +     *
 419  407       * @return the short month strings.
 420  408       */
 421  409      public String[] getShortMonths() {
 422  410          return Arrays.copyOf(shortMonths, shortMonths.length);
 423  411      }
 424  412  
 425  413      /**
 426  414       * Sets short month strings. For example: "Jan", "Feb", etc.
 427  415       * @param newShortMonths the new short month strings.
 428  416       */
↓ open down ↓ 209 lines elided ↑ open up ↑
 638  626  
 639  627      /**
 640  628       * Useful constant for defining time zone offsets.
 641  629       */
 642  630      static final int millisPerHour = 60*60*1000;
 643  631  
 644  632      /**
 645  633       * Cache to hold DateFormatSymbols instances per Locale.
 646  634       */
 647  635      private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
 648      -        = new ConcurrentHashMap<Locale, SoftReference<DateFormatSymbols>>(3);
      636 +        = new ConcurrentHashMap<>(3);
 649  637  
 650  638      private transient int lastZoneIndex = 0;
 651  639  
 652  640      private void initializeData(Locale desiredLocale) {
 653  641          locale = desiredLocale;
 654  642  
 655  643          // Copy values of a cached instance if any.
 656  644          SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
 657  645          DateFormatSymbols dfs;
 658  646          if (ref != null && (dfs = ref.get()) != null) {
 659  647              copyMembers(dfs, this);
 660  648              return;
 661  649          }
 662  650  
 663  651          // Initialize the fields from the ResourceBundle for locale.
 664      -        ResourceBundle resource = LocaleData.getDateFormatData(locale);
      652 +        LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
      653 +        // Avaoid any potential recursions
      654 +        switch (adapter.getAdapterType()) {
      655 +        case HOST:
      656 +        case SPI:
      657 +            adapter = LocaleProviderAdapter.getResourceBundleBased();
      658 +            break;
      659 +        }
      660 +        ResourceBundle resource = adapter.getLocaleData().getDateFormatData(locale);
 665  661  
 666  662          eras = resource.getStringArray("Eras");
 667  663          months = resource.getStringArray("MonthNames");
 668  664          shortMonths = resource.getStringArray("MonthAbbreviations");
 669  665          ampms = resource.getStringArray("AmPmMarkers");
 670  666          localPatternChars = resource.getString("DateTimePatternChars");
 671  667  
 672  668          // Day of week names are stored in a 1-based array.
 673  669          weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
 674  670          shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
      671 +
      672 +        // Put a clone in the cache
      673 +        ref = new SoftReference<>((DateFormatSymbols)this.clone());
      674 +        SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
      675 +        if (x != null) {
      676 +            DateFormatSymbols y = x.get();
      677 +            if (y == null) {
      678 +                // Replace the empty SoftReference with ref.
      679 +                cachedInstances.put(locale, ref);
      680 +            }
      681 +        }
 675  682      }
 676  683  
 677  684      private static String[] toOneBasedArray(String[] src) {
 678  685          int len = src.length;
 679  686          String[] dst = new String[len + 1];
 680  687          dst[0] = "";
 681  688          for (int i = 0; i < len; i++) {
 682  689              dst[i + 1] = src[i];
 683  690          }
 684  691          return dst;
↓ open down ↓ 38 lines elided ↑ open up ↑
 723  730       * it does not need to create a defensive copy.
 724  731       */
 725  732      final String[][] getZoneStringsWrapper() {
 726  733          if (isSubclassObject()) {
 727  734              return getZoneStrings();
 728  735          } else {
 729  736              return getZoneStringsImpl(false);
 730  737          }
 731  738      }
 732  739  
 733      -    private final String[][] getZoneStringsImpl(boolean needsCopy) {
      740 +    private String[][] getZoneStringsImpl(boolean needsCopy) {
 734  741          if (zoneStrings == null) {
 735  742              zoneStrings = TimeZoneNameUtility.getZoneStrings(locale);
 736  743          }
 737  744  
 738  745          if (!needsCopy) {
 739  746              return zoneStrings;
 740  747          }
 741  748  
 742  749          int len = zoneStrings.length;
 743  750          String[][] aCopy = new String[len][];
 744  751          for (int i = 0; i < len; i++) {
 745  752              aCopy[i] = Arrays.copyOf(zoneStrings[i], zoneStrings[i].length);
 746  753          }
 747  754          return aCopy;
 748  755      }
 749  756  
 750      -    private final boolean isSubclassObject() {
      757 +    private boolean isSubclassObject() {
 751  758          return !getClass().getName().equals("java.text.DateFormatSymbols");
 752  759      }
 753  760  
 754  761      /**
 755  762       * Clones all the data members from the source DateFormatSymbols to
 756  763       * the target DateFormatSymbols. This is only for subclasses.
 757  764       * @param src the source DateFormatSymbols.
 758  765       * @param dst the target DateFormatSymbols.
 759  766       */
 760      -    private final void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
      767 +    private void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
 761  768      {
 762  769          dst.eras = Arrays.copyOf(src.eras, src.eras.length);
 763  770          dst.months = Arrays.copyOf(src.months, src.months.length);
 764  771          dst.shortMonths = Arrays.copyOf(src.shortMonths, src.shortMonths.length);
 765  772          dst.weekdays = Arrays.copyOf(src.weekdays, src.weekdays.length);
 766  773          dst.shortWeekdays = Arrays.copyOf(src.shortWeekdays, src.shortWeekdays.length);
 767  774          dst.ampms = Arrays.copyOf(src.ampms, src.ampms.length);
 768  775          if (src.zoneStrings != null) {
 769  776              dst.zoneStrings = src.getZoneStringsImpl(true);
 770  777          } else {
↓ open down ↓ 8 lines elided ↑ open up ↑
 779  786       * sure the backward compatibility.
 780  787       *
 781  788       * @since 1.6
 782  789       */
 783  790      private void writeObject(ObjectOutputStream stream) throws IOException {
 784  791          if (zoneStrings == null) {
 785  792              zoneStrings = TimeZoneNameUtility.getZoneStrings(locale);
 786  793          }
 787  794          stream.defaultWriteObject();
 788  795      }
 789      -
 790      -    /**
 791      -     * Obtains a DateFormatSymbols instance from a DateFormatSymbolsProvider
 792      -     * implementation.
 793      -     */
 794      -    private static class DateFormatSymbolsGetter
 795      -        implements LocaleServiceProviderPool.LocalizedObjectGetter<DateFormatSymbolsProvider,
 796      -                                                                   DateFormatSymbols> {
 797      -        private static final DateFormatSymbolsGetter INSTANCE =
 798      -            new DateFormatSymbolsGetter();
 799      -
 800      -        public DateFormatSymbols getObject(DateFormatSymbolsProvider dateFormatSymbolsProvider,
 801      -                                Locale locale,
 802      -                                String key,
 803      -                                Object... params) {
 804      -            assert params.length == 0;
 805      -            return dateFormatSymbolsProvider.getInstance(locale);
 806      -        }
 807      -    }
 808  796  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX