src/java.base/share/classes/java/nio/charset/Charset.java

Print this page




  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
  23  * questions.
  24  */
  25 
  26 package java.nio.charset;
  27 
  28 import java.nio.ByteBuffer;
  29 import java.nio.CharBuffer;
  30 import java.nio.charset.spi.CharsetProvider;
  31 import java.security.AccessController;
  32 import java.security.PrivilegedAction;

  33 import java.util.Collections;
  34 import java.util.HashSet;
  35 import java.util.Iterator;
  36 import java.util.Locale;
  37 import java.util.Map;
  38 import java.util.NoSuchElementException;
  39 import java.util.Set;
  40 import java.util.ServiceLoader;
  41 import java.util.ServiceConfigurationError;
  42 import java.util.SortedMap;
  43 import java.util.TreeMap;
  44 import sun.misc.ASCIICaseInsensitiveComparator;
  45 import sun.nio.cs.StandardCharsets;
  46 import sun.nio.cs.ThreadLocalCoders;
  47 import sun.security.action.GetPropertyAction;
  48 
  49 
  50 /**
  51  * A named mapping between sequences of sixteen-bit Unicode <a
  52  * href="../../lang/Character.html#unicode">code units</a> and sequences of


 319     /* The standard set of charsets */
 320     private static CharsetProvider standardProvider = new StandardCharsets();
 321 
 322     // Cache of the most-recently-returned charsets,
 323     // along with the names that were used to find them
 324     //
 325     private static volatile Object[] cache1 = null; // "Level 1" cache
 326     private static volatile Object[] cache2 = null; // "Level 2" cache
 327 
 328     private static void cache(String charsetName, Charset cs) {
 329         cache2 = cache1;
 330         cache1 = new Object[] { charsetName, cs };
 331     }
 332 
 333     // Creates an iterator that walks over the available providers, ignoring
 334     // those whose lookup or instantiation causes a security exception to be
 335     // thrown.  Should be invoked with full privileges.
 336     //
 337     private static Iterator<CharsetProvider> providers() {
 338         return new Iterator<>() {
 339 
 340                 ClassLoader cl = ClassLoader.getSystemClassLoader();
 341                 ServiceLoader<CharsetProvider> sl =
 342                     ServiceLoader.load(CharsetProvider.class, cl);
 343                 Iterator<CharsetProvider> i = sl.iterator();
 344 
 345                 CharsetProvider next = null;
 346 
 347                 private boolean getNext() {
 348                     while (next == null) {
 349                         try {
 350                             if (!i.hasNext())
 351                                 return false;
 352                             next = i.next();
 353                         } catch (ServiceConfigurationError sce) {
 354                             if (sce.getCause() instanceof SecurityException) {
 355                                 // Ignore security exceptions
 356                                 continue;
 357                             }
 358                             throw sce;
 359                         }
 360                     }
 361                     return true;
 362                 }
 363 
 364                 public boolean hasNext() {


 407                 new PrivilegedAction<>() {
 408                     public Charset run() {
 409                         for (Iterator<CharsetProvider> i = providers();
 410                              i.hasNext();) {
 411                             CharsetProvider cp = i.next();
 412                             Charset cs = cp.charsetForName(charsetName);
 413                             if (cs != null)
 414                                 return cs;
 415                         }
 416                         return null;
 417                     }
 418                 });
 419 
 420         } finally {
 421             gate.set(null);
 422         }
 423     }
 424 
 425     /* The extended set of charsets */
 426     private static class ExtendedProviderHolder {
 427         static final CharsetProvider extendedProvider = extendedProvider();
 428         // returns ExtendedProvider, if installed
 429         private static CharsetProvider extendedProvider() {
 430             return AccessController.doPrivileged(
 431                        new PrivilegedAction<>() {
 432                            public CharsetProvider run() {
 433                                 try {
 434                                     Class<?> epc
 435                                         = Class.forName("sun.nio.cs.ext.ExtendedCharsets");
 436                                     return (CharsetProvider)epc.newInstance();
 437                                 } catch (ClassNotFoundException x) {
 438                                     // Extended charsets not available
 439                                     // (charsets.jar not present)
 440                                 } catch (InstantiationException |
 441                                          IllegalAccessException x) {
 442                                   throw new Error(x);
 443                                 }
 444                                 return null;
 445                             }
 446                         });

 447         }
 448     }
 449 
 450     private static Charset lookupExtendedCharset(String charsetName) {
 451         CharsetProvider ecp = ExtendedProviderHolder.extendedProvider;
 452         return (ecp != null) ? ecp.charsetForName(charsetName) : null;







 453     }
 454 
 455     private static Charset lookup(String charsetName) {
 456         if (charsetName == null)
 457             throw new IllegalArgumentException("Null charset name");
 458         Object[] a;
 459         if ((a = cache1) != null && charsetName.equals(a[0]))
 460             return (Charset)a[1];
 461         // We expect most programs to use one Charset repeatedly.
 462         // We convey a hint to this effect to the VM by putting the
 463         // level 1 cache miss code in a separate method.
 464         return lookup2(charsetName);
 465     }
 466 
 467     private static Charset lookup2(String charsetName) {
 468         Object[] a;
 469         if ((a = cache2) != null && charsetName.equals(a[0])) {
 470             cache2 = cache1;
 471             cache1 = a;
 472             return (Charset)a[1];


 559      * forName} method, which instead employs an efficient incremental lookup
 560      * algorithm.
 561      *
 562      * <p> This method may return different results at different times if new
 563      * charset providers are dynamically made available to the current Java
 564      * virtual machine.  In the absence of such changes, the charsets returned
 565      * by this method are exactly those that can be retrieved via the {@link
 566      * #forName forName} method.  </p>
 567      *
 568      * @return An immutable, case-insensitive map from canonical charset names
 569      *         to charset objects
 570      */
 571     public static SortedMap<String,Charset> availableCharsets() {
 572         return AccessController.doPrivileged(
 573             new PrivilegedAction<>() {
 574                 public SortedMap<String,Charset> run() {
 575                     TreeMap<String,Charset> m =
 576                         new TreeMap<>(
 577                             ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
 578                     put(standardProvider.charsets(), m);
 579                     CharsetProvider ecp = ExtendedProviderHolder.extendedProvider;
 580                     if (ecp != null)
 581                         put(ecp.charsets(), m);

 582                     for (Iterator<CharsetProvider> i = providers(); i.hasNext();) {
 583                         CharsetProvider cp = i.next();
 584                         put(cp.charsets(), m);
 585                     }
 586                     return Collections.unmodifiableSortedMap(m);
 587                 }
 588             });
 589     }
 590 
 591     private static volatile Charset defaultCharset;
 592 
 593     /**
 594      * Returns the default charset of this Java virtual machine.
 595      *
 596      * <p> The default charset is determined during virtual-machine startup and
 597      * typically depends upon the locale and charset of the underlying
 598      * operating system.
 599      *
 600      * @return  A charset object for the default charset
 601      *




  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
  23  * questions.
  24  */
  25 
  26 package java.nio.charset;
  27 
  28 import java.nio.ByteBuffer;
  29 import java.nio.CharBuffer;
  30 import java.nio.charset.spi.CharsetProvider;
  31 import java.security.AccessController;
  32 import java.security.PrivilegedAction;
  33 import java.util.Arrays;
  34 import java.util.Collections;
  35 import java.util.HashSet;
  36 import java.util.Iterator;
  37 import java.util.Locale;
  38 import java.util.Map;
  39 import java.util.NoSuchElementException;
  40 import java.util.Set;
  41 import java.util.ServiceLoader;
  42 import java.util.ServiceConfigurationError;
  43 import java.util.SortedMap;
  44 import java.util.TreeMap;
  45 import sun.misc.ASCIICaseInsensitiveComparator;
  46 import sun.nio.cs.StandardCharsets;
  47 import sun.nio.cs.ThreadLocalCoders;
  48 import sun.security.action.GetPropertyAction;
  49 
  50 
  51 /**
  52  * A named mapping between sequences of sixteen-bit Unicode <a
  53  * href="../../lang/Character.html#unicode">code units</a> and sequences of


 320     /* The standard set of charsets */
 321     private static CharsetProvider standardProvider = new StandardCharsets();
 322 
 323     // Cache of the most-recently-returned charsets,
 324     // along with the names that were used to find them
 325     //
 326     private static volatile Object[] cache1 = null; // "Level 1" cache
 327     private static volatile Object[] cache2 = null; // "Level 2" cache
 328 
 329     private static void cache(String charsetName, Charset cs) {
 330         cache2 = cache1;
 331         cache1 = new Object[] { charsetName, cs };
 332     }
 333 
 334     // Creates an iterator that walks over the available providers, ignoring
 335     // those whose lookup or instantiation causes a security exception to be
 336     // thrown.  Should be invoked with full privileges.
 337     //
 338     private static Iterator<CharsetProvider> providers() {
 339         return new Iterator<>() {

 340                 ClassLoader cl = ClassLoader.getSystemClassLoader();
 341                 ServiceLoader<CharsetProvider> sl =
 342                     ServiceLoader.load(CharsetProvider.class, cl);
 343                 Iterator<CharsetProvider> i = sl.iterator();

 344                 CharsetProvider next = null;
 345 
 346                 private boolean getNext() {
 347                     while (next == null) {
 348                         try {
 349                             if (!i.hasNext())
 350                                 return false;
 351                             next = i.next();
 352                         } catch (ServiceConfigurationError sce) {
 353                             if (sce.getCause() instanceof SecurityException) {
 354                                 // Ignore security exceptions
 355                                 continue;
 356                             }
 357                             throw sce;
 358                         }
 359                     }
 360                     return true;
 361                 }
 362 
 363                 public boolean hasNext() {


 406                 new PrivilegedAction<>() {
 407                     public Charset run() {
 408                         for (Iterator<CharsetProvider> i = providers();
 409                              i.hasNext();) {
 410                             CharsetProvider cp = i.next();
 411                             Charset cs = cp.charsetForName(charsetName);
 412                             if (cs != null)
 413                                 return cs;
 414                         }
 415                         return null;
 416                     }
 417                 });
 418 
 419         } finally {
 420             gate.set(null);
 421         }
 422     }
 423 
 424     /* The extended set of charsets */
 425     private static class ExtendedProviderHolder {
 426         static final CharsetProvider[] extendedProviders = extendedProviders();
 427         // returns ExtendedProvider, if installed
 428         private static CharsetProvider[] extendedProviders() {
 429             return AccessController.doPrivileged(new PrivilegedAction<>() {
 430                     public CharsetProvider[] run() {
 431                         CharsetProvider[] cps = new CharsetProvider[1];
 432                         int n = 0;
 433                         ServiceLoader<CharsetProvider> sl =
 434                             ServiceLoader.loadInstalled(CharsetProvider.class);
 435                         for (CharsetProvider cp : sl) {
 436                             if (n + 1 > cps.length) {
 437                                 cps = Arrays.copyOf(cps, cps.length << 1);




 438                             }
 439                             cps[n++] = cp;
 440                         }
 441                         return n == cps.length ? cps : Arrays.copyOf(cps, n);
 442                     }});
 443         }
 444     }
 445 
 446     private static Charset lookupExtendedCharset(String charsetName) {
 447         if (!sun.misc.VM.isBooted())  // see lookupViaProviders()
 448             return null;
 449         CharsetProvider[] ecps = ExtendedProviderHolder.extendedProviders;
 450         for (CharsetProvider cp : ecps) {
 451             Charset cs = cp.charsetForName(charsetName);
 452             if (cs != null)
 453                 return cs;
 454         }
 455         return null;
 456     }
 457 
 458     private static Charset lookup(String charsetName) {
 459         if (charsetName == null)
 460             throw new IllegalArgumentException("Null charset name");
 461         Object[] a;
 462         if ((a = cache1) != null && charsetName.equals(a[0]))
 463             return (Charset)a[1];
 464         // We expect most programs to use one Charset repeatedly.
 465         // We convey a hint to this effect to the VM by putting the
 466         // level 1 cache miss code in a separate method.
 467         return lookup2(charsetName);
 468     }
 469 
 470     private static Charset lookup2(String charsetName) {
 471         Object[] a;
 472         if ((a = cache2) != null && charsetName.equals(a[0])) {
 473             cache2 = cache1;
 474             cache1 = a;
 475             return (Charset)a[1];


 562      * forName} method, which instead employs an efficient incremental lookup
 563      * algorithm.
 564      *
 565      * <p> This method may return different results at different times if new
 566      * charset providers are dynamically made available to the current Java
 567      * virtual machine.  In the absence of such changes, the charsets returned
 568      * by this method are exactly those that can be retrieved via the {@link
 569      * #forName forName} method.  </p>
 570      *
 571      * @return An immutable, case-insensitive map from canonical charset names
 572      *         to charset objects
 573      */
 574     public static SortedMap<String,Charset> availableCharsets() {
 575         return AccessController.doPrivileged(
 576             new PrivilegedAction<>() {
 577                 public SortedMap<String,Charset> run() {
 578                     TreeMap<String,Charset> m =
 579                         new TreeMap<>(
 580                             ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
 581                     put(standardProvider.charsets(), m);
 582                     CharsetProvider[] ecps = ExtendedProviderHolder.extendedProviders;
 583                     for (CharsetProvider ecp :ecps) {
 584                         put(ecp.charsets(), m);
 585                     }
 586                     for (Iterator<CharsetProvider> i = providers(); i.hasNext();) {
 587                         CharsetProvider cp = i.next();
 588                         put(cp.charsets(), m);
 589                     }
 590                     return Collections.unmodifiableSortedMap(m);
 591                 }
 592             });
 593     }
 594 
 595     private static volatile Charset defaultCharset;
 596 
 597     /**
 598      * Returns the default charset of this Java virtual machine.
 599      *
 600      * <p> The default charset is determined during virtual-machine startup and
 601      * typically depends upon the locale and charset of the underlying
 602      * operating system.
 603      *
 604      * @return  A charset object for the default charset
 605      *