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

Print this page

        

@@ -28,10 +28,11 @@
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.spi.CharsetProvider;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.Map;

@@ -334,16 +335,14 @@
     // those whose lookup or instantiation causes a security exception to be
     // thrown.  Should be invoked with full privileges.
     //
     private static Iterator<CharsetProvider> providers() {
         return new Iterator<>() {
-
                 ClassLoader cl = ClassLoader.getSystemClassLoader();
                 ServiceLoader<CharsetProvider> sl =
                     ServiceLoader.load(CharsetProvider.class, cl);
                 Iterator<CharsetProvider> i = sl.iterator();
-
                 CharsetProvider next = null;
 
                 private boolean getNext() {
                     while (next == null) {
                         try {

@@ -422,36 +421,40 @@
         }
     }
 
     /* The extended set of charsets */
     private static class ExtendedProviderHolder {
-        static final CharsetProvider extendedProvider = extendedProvider();
+        static final CharsetProvider[] extendedProviders = extendedProviders();
         // returns ExtendedProvider, if installed
-        private static CharsetProvider extendedProvider() {
-            return AccessController.doPrivileged(
-                       new PrivilegedAction<>() {
-                           public CharsetProvider run() {
-                                try {
-                                    Class<?> epc
-                                        = Class.forName("sun.nio.cs.ext.ExtendedCharsets");
-                                    return (CharsetProvider)epc.newInstance();
-                                } catch (ClassNotFoundException x) {
-                                    // Extended charsets not available
-                                    // (charsets.jar not present)
-                                } catch (InstantiationException |
-                                         IllegalAccessException x) {
-                                  throw new Error(x);
+        private static CharsetProvider[] extendedProviders() {
+            return AccessController.doPrivileged(new PrivilegedAction<>() {
+                    public CharsetProvider[] run() {
+                        CharsetProvider[] cps = new CharsetProvider[1];
+                        int n = 0;
+                        ServiceLoader<CharsetProvider> sl =
+                            ServiceLoader.loadInstalled(CharsetProvider.class);
+                        for (CharsetProvider cp : sl) {
+                            if (n + 1 > cps.length) {
+                                cps = Arrays.copyOf(cps, cps.length << 1);
                                 }
-                                return null;
+                            cps[n++] = cp;
                             }
-                        });
+                        return n == cps.length ? cps : Arrays.copyOf(cps, n);
+                    }});
         }
     }
 
     private static Charset lookupExtendedCharset(String charsetName) {
-        CharsetProvider ecp = ExtendedProviderHolder.extendedProvider;
-        return (ecp != null) ? ecp.charsetForName(charsetName) : null;
+        if (!sun.misc.VM.isBooted())  // see lookupViaProviders()
+            return null;
+        CharsetProvider[] ecps = ExtendedProviderHolder.extendedProviders;
+        for (CharsetProvider cp : ecps) {
+            Charset cs = cp.charsetForName(charsetName);
+            if (cs != null)
+                return cs;
+        }
+        return null;
     }
 
     private static Charset lookup(String charsetName) {
         if (charsetName == null)
             throw new IllegalArgumentException("Null charset name");

@@ -574,13 +577,14 @@
                 public SortedMap<String,Charset> run() {
                     TreeMap<String,Charset> m =
                         new TreeMap<>(
                             ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
                     put(standardProvider.charsets(), m);
-                    CharsetProvider ecp = ExtendedProviderHolder.extendedProvider;
-                    if (ecp != null)
+                    CharsetProvider[] ecps = ExtendedProviderHolder.extendedProviders;
+                    for (CharsetProvider ecp :ecps) {
                         put(ecp.charsets(), m);
+                    }
                     for (Iterator<CharsetProvider> i = providers(); i.hasNext();) {
                         CharsetProvider cp = i.next();
                         put(cp.charsets(), m);
                     }
                     return Collections.unmodifiableSortedMap(m);