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/Collator.java
          +++ new/src/share/classes/java/text/Collator.java
   1    1  /*
   2      - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
        2 + * Copyright (c) 1997, 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 ↓ 18 lines elided ↑ open up ↑
  31   31   * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  32   32   * materials are provided under terms of a License Agreement between Taligent
  33   33   * and Sun. This technology is protected by multiple US and International
  34   34   * patents. This notice and attribution to Taligent may not be removed.
  35   35   *   Taligent is a registered trademark of Taligent, Inc.
  36   36   *
  37   37   */
  38   38  
  39   39  package java.text;
  40   40  
       41 +import java.lang.ref.SoftReference;
  41   42  import java.text.spi.CollatorProvider;
  42   43  import java.util.Locale;
  43      -import java.util.MissingResourceException;
  44   44  import java.util.ResourceBundle;
  45      -import java.util.spi.LocaleServiceProvider;
  46      -import sun.misc.SoftCache;
  47      -import sun.util.resources.LocaleData;
  48      -import sun.util.LocaleServiceProviderPool;
       45 +import java.util.concurrent.ConcurrentHashMap;
       46 +import java.util.concurrent.ConcurrentMap;
       47 +import sun.util.locale.provider.LocaleProviderAdapter;
       48 +import sun.util.locale.provider.LocaleServiceProviderPool;
  49   49  
  50   50  
  51   51  /**
  52   52   * The <code>Collator</code> class performs locale-sensitive
  53   53   * <code>String</code> comparison. You use this class to build
  54   54   * searching and sorting routines for natural language text.
  55   55   *
  56   56   * <p>
  57   57   * <code>Collator</code> is an abstract base class. Subclasses
  58   58   * implement specific collation strategies. One subclass,
↓ open down ↓ 165 lines elided ↑ open up ↑
 224  224          return getInstance(Locale.getDefault());
 225  225      }
 226  226  
 227  227      /**
 228  228       * Gets the Collator for the desired locale.
 229  229       * @param desiredLocale the desired locale.
 230  230       * @return the Collator for the desired locale.
 231  231       * @see java.util.Locale
 232  232       * @see java.util.ResourceBundle
 233  233       */
 234      -    public static synchronized
 235      -    Collator getInstance(Locale desiredLocale)
 236      -    {
 237      -        Collator result = (Collator) cache.get(desiredLocale);
 238      -        if (result != null) {
 239      -                 return (Collator)result.clone();  // make the world safe
 240      -        }
 241      -
 242      -        // Check whether a provider can provide an implementation that's closer
 243      -        // to the requested locale than what the Java runtime itself can provide.
 244      -        LocaleServiceProviderPool pool =
 245      -            LocaleServiceProviderPool.getPool(CollatorProvider.class);
 246      -        if (pool.hasProviders()) {
 247      -            Collator providersInstance = pool.getLocalizedObject(
 248      -                                            CollatorGetter.INSTANCE,
 249      -                                            desiredLocale,
 250      -                                            desiredLocale);
 251      -            if (providersInstance != null) {
 252      -                return providersInstance;
      234 +    public static Collator getInstance(Locale desiredLocale) {
      235 +        SoftReference<Collator> ref = cache.get(desiredLocale);
      236 +        Collator result = (ref != null) ? ref.get() : null;
      237 +        if (result == null) {
      238 +            LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(CollatorProvider.class,
      239 +                                                                     desiredLocale);
      240 +            CollatorProvider provider = adapter.getCollatorProvider();
      241 +            result = provider.getInstance(desiredLocale);
      242 +            if (result == null) {
      243 +                if (adapter.getAdapterType() != LocaleProviderAdapter.Type.JRE) {
      244 +                    result = LocaleProviderAdapter.forJRE()
      245 +                             .getCollatorProvider().getInstance(desiredLocale);
      246 +                }
      247 +                if (result == null) {
      248 +                    throw new InternalError("Collator instance creation failed. (provider="
      249 +                                           + provider + ")");
 253  250              }
 254      -        }
 255      -
 256      -        // Load the resource of the desired locale from resource
 257      -        // manager.
 258      -        String colString = "";
 259      -        try {
 260      -            ResourceBundle resource = LocaleData.getCollationData(desiredLocale);
 261      -
 262      -            colString = resource.getString("Rule");
 263      -        } catch (MissingResourceException e) {
 264      -            // Use default values
 265      -        }
 266      -        try
 267      -        {
 268      -            result = new RuleBasedCollator( CollationRules.DEFAULTRULES +
 269      -                                            colString,
 270      -                                            CANONICAL_DECOMPOSITION );
 271      -        }
 272      -        catch(ParseException foo)
 273      -        {
 274      -            // predefined tables should contain correct grammar
 275      -            try {
 276      -                result = new RuleBasedCollator( CollationRules.DEFAULTRULES );
 277      -            } catch (ParseException bar) {
 278      -                // do nothing
 279  251              }
      252 +            while (true) {
      253 +                if (ref != null) {
      254 +                    // Remove the empty SoftReference if any
      255 +                    cache.remove(desiredLocale, ref);
      256 +                }
      257 +                ref = cache.putIfAbsent(desiredLocale, new SoftReference<>(result));
      258 +                if (ref == null) {
      259 +                    break;
      260 +                }
      261 +                Collator cachedColl = ref.get();
      262 +                if (cachedColl != null) {
      263 +                    result = cachedColl;
      264 +                    break;
      265 +                }
      266 +            }
 280  267          }
 281      -        // Now that RuleBasedCollator adds expansions for pre-composed characters
 282      -        // into their decomposed equivalents, the default collators don't need
 283      -        // to have decomposition turned on.  Laura, 5/5/98, bug 4114077
 284      -        result.setDecomposition(NO_DECOMPOSITION);
 285      -
 286      -        cache.put(desiredLocale,result);
 287      -        return (Collator)result.clone();
      268 +        return (Collator) result.clone(); // make the world safe
 288  269      }
 289  270  
 290  271      /**
 291  272       * Compares the source string to the target string according to the
 292  273       * collation rules for this Collator.  Returns an integer less than,
 293  274       * equal to or greater than zero depending on whether the source String is
 294  275       * less than, equal to or greater than the target string.  See the Collator
 295  276       * class description for an example of use.
 296  277       * <p>
 297  278       * For a one time comparison, this method has the best performance. If a
↓ open down ↓ 18 lines elided ↑ open up ↑
 316  297       * This implementation merely returns
 317  298       *  <code> compare((String)o1, (String)o2) </code>.
 318  299       *
 319  300       * @return a negative integer, zero, or a positive integer as the
 320  301       *         first argument is less than, equal to, or greater than the
 321  302       *         second.
 322  303       * @exception ClassCastException the arguments cannot be cast to Strings.
 323  304       * @see java.util.Comparator
 324  305       * @since   1.2
 325  306       */
      307 +    @Override
 326  308      public int compare(Object o1, Object o2) {
 327  309      return compare((String)o1, (String)o2);
 328  310      }
 329  311  
 330  312      /**
 331  313       * Transforms the String into a series of bits that can be compared bitwise
 332  314       * to other CollationKeys. CollationKeys provide better performance than
 333  315       * Collator.compare when Strings are involved in multiple comparisons.
 334  316       * See the Collator class description for an example using CollationKeys.
 335  317       * @param source the string to be transformed into a collation key.
↓ open down ↓ 44 lines elided ↑ open up ↑
 380  362       * @see java.text.Collator#SECONDARY
 381  363       * @see java.text.Collator#TERTIARY
 382  364       * @see java.text.Collator#IDENTICAL
 383  365       * @exception  IllegalArgumentException If the new strength value is not one of
 384  366       * PRIMARY, SECONDARY, TERTIARY or IDENTICAL.
 385  367       */
 386  368      public synchronized void setStrength(int newStrength) {
 387  369          if ((newStrength != PRIMARY) &&
 388  370              (newStrength != SECONDARY) &&
 389  371              (newStrength != TERTIARY) &&
 390      -            (newStrength != IDENTICAL))
      372 +            (newStrength != IDENTICAL)) {
 391  373              throw new IllegalArgumentException("Incorrect comparison level.");
      374 +        }
 392  375          strength = newStrength;
 393  376      }
 394  377  
 395  378      /**
 396  379       * Get the decomposition mode of this Collator. Decomposition mode
 397  380       * determines how Unicode composed characters are handled. Adjusting
 398  381       * decomposition mode allows the user to select between faster and more
 399  382       * complete collation behavior.
 400  383       * <p>The three values for decomposition mode are:
 401  384       * <UL>
↓ open down ↓ 20 lines elided ↑ open up ↑
 422  405       * @see java.text.Collator#getDecomposition
 423  406       * @see java.text.Collator#NO_DECOMPOSITION
 424  407       * @see java.text.Collator#CANONICAL_DECOMPOSITION
 425  408       * @see java.text.Collator#FULL_DECOMPOSITION
 426  409       * @exception IllegalArgumentException If the given value is not a valid decomposition
 427  410       * mode.
 428  411       */
 429  412      public synchronized void setDecomposition(int decompositionMode) {
 430  413          if ((decompositionMode != NO_DECOMPOSITION) &&
 431  414              (decompositionMode != CANONICAL_DECOMPOSITION) &&
 432      -            (decompositionMode != FULL_DECOMPOSITION))
      415 +            (decompositionMode != FULL_DECOMPOSITION)) {
 433  416              throw new IllegalArgumentException("Wrong decomposition mode.");
      417 +        }
 434  418          decmp = decompositionMode;
 435  419      }
 436  420  
 437  421      /**
 438  422       * Returns an array of all locales for which the
 439  423       * <code>getInstance</code> methods of this class can return
 440  424       * localized instances.
 441  425       * The returned array represents the union of locales supported
 442  426       * by the Java runtime and by installed
 443  427       * {@link java.text.spi.CollatorProvider CollatorProvider} implementations.
↓ open down ↓ 5 lines elided ↑ open up ↑
 449  433       */
 450  434      public static synchronized Locale[] getAvailableLocales() {
 451  435          LocaleServiceProviderPool pool =
 452  436              LocaleServiceProviderPool.getPool(CollatorProvider.class);
 453  437          return pool.getAvailableLocales();
 454  438      }
 455  439  
 456  440      /**
 457  441       * Overrides Cloneable
 458  442       */
      443 +    @Override
 459  444      public Object clone()
 460  445      {
 461  446          try {
 462  447              return (Collator)super.clone();
 463  448          } catch (CloneNotSupportedException e) {
 464  449              throw new InternalError(e);
 465  450          }
 466  451      }
 467  452  
 468  453      /**
 469  454       * Compares the equality of two Collators.
 470  455       * @param that the Collator to be compared with this.
 471  456       * @return true if this Collator is the same as that Collator;
 472  457       * false otherwise.
 473  458       */
      459 +    @Override
 474  460      public boolean equals(Object that)
 475  461      {
 476      -        if (this == that) return true;
 477      -        if (that == null) return false;
 478      -        if (getClass() != that.getClass()) return false;
      462 +        if (this == that) {
      463 +            return true;
      464 +        }
      465 +        if (that == null) {
      466 +            return false;
      467 +        }
      468 +        if (getClass() != that.getClass()) {
      469 +            return false;
      470 +        }
 479  471          Collator other = (Collator) that;
 480  472          return ((strength == other.strength) &&
 481  473                  (decmp == other.decmp));
 482  474      }
 483  475  
 484  476      /**
 485  477       * Generates the hash code for this Collator.
 486  478       */
      479 +    @Override
 487  480      abstract public int hashCode();
 488  481  
 489  482      /**
 490  483       * Default constructor.  This constructor is
 491  484       * protected so subclasses can get access to it. Users typically create
 492  485       * a Collator sub-class by calling the factory method getInstance.
 493  486       * @see java.text.Collator#getInstance
 494  487       */
 495  488      protected Collator()
 496  489      {
 497  490          strength = TERTIARY;
 498  491          decmp = CANONICAL_DECOMPOSITION;
 499  492      }
 500  493  
 501  494      private int strength = 0;
 502  495      private int decmp = 0;
 503      -    private static SoftCache cache = new SoftCache();
      496 +    private static final ConcurrentMap<Locale, SoftReference<Collator>> cache
      497 +            = new ConcurrentHashMap<>();
 504  498  
 505  499      //
 506  500      // FIXME: These three constants should be removed.
 507  501      //
 508  502      /**
 509  503       * LESS is returned if source string is compared to be less than target
 510  504       * string in the compare() method.
 511  505       * @see java.text.Collator#compare
 512  506       */
 513  507      final static int LESS = -1;
↓ open down ↓ 2 lines elided ↑ open up ↑
 516  510       * string in the compare() method.
 517  511       * @see java.text.Collator#compare
 518  512       */
 519  513      final static int EQUAL = 0;
 520  514      /**
 521  515       * GREATER is returned if source string is compared to be greater than
 522  516       * target string in the compare() method.
 523  517       * @see java.text.Collator#compare
 524  518       */
 525  519      final static int GREATER = 1;
 526      -
 527      -    /**
 528      -     * Obtains a Collator instance from a CollatorProvider
 529      -     * implementation.
 530      -     */
 531      -    private static class CollatorGetter
 532      -        implements LocaleServiceProviderPool.LocalizedObjectGetter<CollatorProvider, Collator> {
 533      -        private static final CollatorGetter INSTANCE = new CollatorGetter();
 534      -
 535      -        public Collator getObject(CollatorProvider collatorProvider,
 536      -                                Locale locale,
 537      -                                String key,
 538      -                                Object... params) {
 539      -            assert params.length == 1;
 540      -            Collator result = collatorProvider.getInstance(locale);
 541      -            if (result != null) {
 542      -                // put this Collator instance in the cache for two locales, one
 543      -                // is for the desired locale, and the other is for the actual
 544      -                // locale where the provider is found, which may be a fall back locale.
 545      -                cache.put((Locale)params[0], result);
 546      -                cache.put(locale, result);
 547      -                return (Collator)result.clone();
 548      -            }
 549      -
 550      -            return null;
 551      -        }
 552      -    }
 553  520   }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX