src/share/classes/java/text/Collator.java

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)

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -36,18 +36,18 @@
  *
  */
 
 package java.text;
 
+import java.lang.ref.SoftReference;
 import java.text.spi.CollatorProvider;
 import java.util.Locale;
-import java.util.MissingResourceException;
 import java.util.ResourceBundle;
-import java.util.spi.LocaleServiceProvider;
-import sun.misc.SoftCache;
-import sun.util.resources.LocaleData;
-import sun.util.LocaleServiceProviderPool;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import sun.util.locale.provider.LocaleProviderAdapter;
+import sun.util.locale.provider.LocaleServiceProviderPool;
 
 
 /**
  * The <code>Collator</code> class performs locale-sensitive
  * <code>String</code> comparison. You use this class to build

@@ -229,65 +229,46 @@
      * @param desiredLocale the desired locale.
      * @return the Collator for the desired locale.
      * @see java.util.Locale
      * @see java.util.ResourceBundle
      */
-    public static synchronized
-    Collator getInstance(Locale desiredLocale)
-    {
-        Collator result = (Collator) cache.get(desiredLocale);
-        if (result != null) {
-                 return (Collator)result.clone();  // make the world safe
-        }
-
-        // Check whether a provider can provide an implementation that's closer
-        // to the requested locale than what the Java runtime itself can provide.
-        LocaleServiceProviderPool pool =
-            LocaleServiceProviderPool.getPool(CollatorProvider.class);
-        if (pool.hasProviders()) {
-            Collator providersInstance = pool.getLocalizedObject(
-                                            CollatorGetter.INSTANCE,
-                                            desiredLocale,
+    public static Collator getInstance(Locale desiredLocale) {
+        SoftReference<Collator> ref = cache.get(desiredLocale);
+        Collator result = (ref != null) ? ref.get() : null;
+        if (result == null) {
+            LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(CollatorProvider.class,
                                             desiredLocale);
-            if (providersInstance != null) {
-                return providersInstance;
+            CollatorProvider provider = adapter.getCollatorProvider();
+            result = provider.getInstance(desiredLocale);
+            if (result == null) {
+                if (adapter.getAdapterType() != LocaleProviderAdapter.Type.JRE) {
+                    result = LocaleProviderAdapter.forJRE()
+                             .getCollatorProvider().getInstance(desiredLocale);
             }
+                if (result == null) {
+                    throw new InternalError("Collator instance creation failed. (provider="
+                                           + provider + ")");
         }
-
-        // Load the resource of the desired locale from resource
-        // manager.
-        String colString = "";
-        try {
-            ResourceBundle resource = LocaleData.getCollationData(desiredLocale);
-
-            colString = resource.getString("Rule");
-        } catch (MissingResourceException e) {
-            // Use default values
         }
-        try
-        {
-            result = new RuleBasedCollator( CollationRules.DEFAULTRULES +
-                                            colString,
-                                            CANONICAL_DECOMPOSITION );
+            while (true) {
+                if (ref != null) {
+                    // Remove the empty SoftReference if any
+                    cache.remove(desiredLocale, ref);
         }
-        catch(ParseException foo)
-        {
-            // predefined tables should contain correct grammar
-            try {
-                result = new RuleBasedCollator( CollationRules.DEFAULTRULES );
-            } catch (ParseException bar) {
-                // do nothing
+                ref = cache.putIfAbsent(desiredLocale, new SoftReference<>(result));
+                if (ref == null) {
+                    break;
             }
+                Collator cachedColl = ref.get();
+                if (cachedColl != null) {
+                    result = cachedColl;
+                    break;
         }
-        // Now that RuleBasedCollator adds expansions for pre-composed characters
-        // into their decomposed equivalents, the default collators don't need
-        // to have decomposition turned on.  Laura, 5/5/98, bug 4114077
-        result.setDecomposition(NO_DECOMPOSITION);
-
-        cache.put(desiredLocale,result);
-        return (Collator)result.clone();
     }
+        }
+        return (Collator) result.clone(); // make the world safe
+    }
 
     /**
      * Compares the source string to the target string according to the
      * collation rules for this Collator.  Returns an integer less than,
      * equal to or greater than zero depending on whether the source String is

@@ -321,10 +302,11 @@
      *         second.
      * @exception ClassCastException the arguments cannot be cast to Strings.
      * @see java.util.Comparator
      * @since   1.2
      */
+    @Override
     public int compare(Object o1, Object o2) {
     return compare((String)o1, (String)o2);
     }
 
     /**

@@ -385,12 +367,13 @@
      */
     public synchronized void setStrength(int newStrength) {
         if ((newStrength != PRIMARY) &&
             (newStrength != SECONDARY) &&
             (newStrength != TERTIARY) &&
-            (newStrength != IDENTICAL))
+            (newStrength != IDENTICAL)) {
             throw new IllegalArgumentException("Incorrect comparison level.");
+        }
         strength = newStrength;
     }
 
     /**
      * Get the decomposition mode of this Collator. Decomposition mode

@@ -427,12 +410,13 @@
      * mode.
      */
     public synchronized void setDecomposition(int decompositionMode) {
         if ((decompositionMode != NO_DECOMPOSITION) &&
             (decompositionMode != CANONICAL_DECOMPOSITION) &&
-            (decompositionMode != FULL_DECOMPOSITION))
+            (decompositionMode != FULL_DECOMPOSITION)) {
             throw new IllegalArgumentException("Wrong decomposition mode.");
+        }
         decmp = decompositionMode;
     }
 
     /**
      * Returns an array of all locales for which the

@@ -454,10 +438,11 @@
     }
 
     /**
      * Overrides Cloneable
      */
+    @Override
     public Object clone()
     {
         try {
             return (Collator)super.clone();
         } catch (CloneNotSupportedException e) {

@@ -469,23 +454,31 @@
      * Compares the equality of two Collators.
      * @param that the Collator to be compared with this.
      * @return true if this Collator is the same as that Collator;
      * false otherwise.
      */
+    @Override
     public boolean equals(Object that)
     {
-        if (this == that) return true;
-        if (that == null) return false;
-        if (getClass() != that.getClass()) return false;
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
         Collator other = (Collator) that;
         return ((strength == other.strength) &&
                 (decmp == other.decmp));
     }
 
     /**
      * Generates the hash code for this Collator.
      */
+    @Override
     abstract public int hashCode();
 
     /**
      * Default constructor.  This constructor is
      * protected so subclasses can get access to it. Users typically create

@@ -498,11 +491,12 @@
         decmp = CANONICAL_DECOMPOSITION;
     }
 
     private int strength = 0;
     private int decmp = 0;
-    private static SoftCache cache = new SoftCache();
+    private static final ConcurrentMap<Locale, SoftReference<Collator>> cache
+            = new ConcurrentHashMap<>();
 
     //
     // FIXME: These three constants should be removed.
     //
     /**

@@ -521,33 +515,6 @@
      * GREATER is returned if source string is compared to be greater than
      * target string in the compare() method.
      * @see java.text.Collator#compare
      */
     final static int GREATER = 1;
-
-    /**
-     * Obtains a Collator instance from a CollatorProvider
-     * implementation.
-     */
-    private static class CollatorGetter
-        implements LocaleServiceProviderPool.LocalizedObjectGetter<CollatorProvider, Collator> {
-        private static final CollatorGetter INSTANCE = new CollatorGetter();
-
-        public Collator getObject(CollatorProvider collatorProvider,
-                                Locale locale,
-                                String key,
-                                Object... params) {
-            assert params.length == 1;
-            Collator result = collatorProvider.getInstance(locale);
-            if (result != null) {
-                // put this Collator instance in the cache for two locales, one
-                // is for the desired locale, and the other is for the actual
-                // locale where the provider is found, which may be a fall back locale.
-                cache.put((Locale)params[0], result);
-                cache.put(locale, result);
-                return (Collator)result.clone();
-            }
-
-            return null;
-        }
-    }
  }