📄 charset.java
字号:
private static volatile Object[] cache1 = null; // "Level 1" cache private static volatile Object[] cache2 = null; // "Level 2" cache private static void cache(String charsetName, Charset cs) { cache2 = cache1; cache1 = new Object[] { charsetName, cs }; } // Creates an iterator that walks over the available providers, ignoring // those whose lookup or instantiation causes a security exception to be // thrown. Should be invoked with full privileges. // private static Iterator providers() { return new Iterator() { Class c = java.nio.charset.spi.CharsetProvider.class; ClassLoader cl = ClassLoader.getSystemClassLoader(); Iterator i = Service.providers(c, cl); Object next = null; private boolean getNext() { while (next == null) { try { if (!i.hasNext()) return false; next = i.next(); } catch (ServiceConfigurationError sce) { if (sce.getCause() instanceof SecurityException) { // Ignore security exceptions continue; } throw sce; } } return true; } public boolean hasNext() { return getNext(); } public Object next() { if (!getNext()) throw new NoSuchElementException(); Object n = next; next = null; return n; } public void remove() { throw new UnsupportedOperationException(); } }; } // Thread-local gate to prevent recursive provider lookups private static ThreadLocal gate = new ThreadLocal(); private static Charset lookupViaProviders(final String charsetName) { // The runtime startup sequence looks up standard charsets as a // consequence of the VM's invocation of System.initializeSystemClass // in order to, e.g., set system properties and encode filenames. At // that point the application class loader has not been initialized, // however, so we can't look for providers because doing so will cause // that loader to be prematurely initialized with incomplete // information. // if (!sun.misc.VM.isBooted()) return null; if (gate.get() != null) // Avoid recursive provider lookups return null; try { gate.set(gate); return (Charset)AccessController .doPrivileged(new PrivilegedAction() { public Object run() { for (Iterator i = providers(); i.hasNext();) { CharsetProvider cp = (CharsetProvider)i.next(); Charset cs = cp.charsetForName(charsetName); if (cs != null) return cs; } return null; } }); } finally { gate.set(null); } } /* The extended set of charsets */ private static Object extendedProviderLock = new Object(); private static boolean extendedProviderProbed = false; private static CharsetProvider extendedProvider = null; private static void probeExtendedProvider() { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { Class epc = Class.forName("sun.nio.cs.ext.ExtendedCharsets"); extendedProvider = (CharsetProvider)epc.newInstance(); } catch (ClassNotFoundException x) { // Extended charsets not available // (charsets.jar not present) } catch (InstantiationException x) { throw new Error(x); } catch (IllegalAccessException x) { throw new Error(x); } return null; } }); } private static Charset lookupExtendedCharset(String charsetName) { CharsetProvider ecp = null; synchronized (extendedProviderLock) { if (!extendedProviderProbed) { probeExtendedProvider(); extendedProviderProbed = true; } ecp = extendedProvider; } return (ecp != null) ? ecp.charsetForName(charsetName) : null; } private static Charset lookup(String charsetName) { if (charsetName == null) throw new IllegalArgumentException("Null charset name"); Object[] a; if ((a = cache1) != null && charsetName.equals(a[0])) return (Charset)a[1]; // We expect most programs to use one Charset repeatedly. // We convey a hint to this effect to the VM by putting the // level 1 cache miss code in a separate method. return lookup2(charsetName); } private static Charset lookup2(String charsetName) { Object[] a; if ((a = cache2) != null && charsetName.equals(a[0])) { cache2 = cache1; cache1 = a; return (Charset)a[1]; } Charset cs; if ((cs = standardProvider.charsetForName(charsetName)) != null || (cs = lookupExtendedCharset(charsetName)) != null || (cs = lookupViaProviders(charsetName)) != null) { cache(charsetName, cs); return cs; } /* Only need to check the name if we didn't find a charset for it */ checkName(charsetName); return null; } /** * Tells whether the named charset is supported. </p> * * @param charsetName * The name of the requested charset; may be either * a canonical name or an alias * * @return <tt>true</tt> if, and only if, support for the named charset * is available in the current Java virtual machine * * @throws IllegalCharsetNameException * If the given charset name is illegal */ public static boolean isSupported(String charsetName) { return (lookup(charsetName) != null); } /** * Returns a charset object for the named charset. </p> * * @param charsetName * The name of the requested charset; may be either * a canonical name or an alias * * @return A charset object for the named charset * * @throws IllegalCharsetNameException * If the given charset name is illegal * * @throws UnsupportedCharsetException * If no support for the named charset is available * in this instance of the Java virtual machine */ public static Charset forName(String charsetName) { Charset cs = lookup(charsetName); if (cs != null) return cs; throw new UnsupportedCharsetException(charsetName); } // Fold charsets from the given iterator into the given map, ignoring // charsets whose names already have entries in the map. // private static void put(Iterator i, Map m) { while (i.hasNext()) { Charset cs = (Charset)i.next(); if (!m.containsKey(cs.name())) m.put(cs.name(), cs); } } /** * Constructs a sorted map from canonical charset names to charset objects. * * <p> The map returned by this method will have one entry for each charset * for which support is available in the current Java virtual machine. If * two or more supported charsets have the same canonical name then the * resulting map will contain just one of them; which one it will contain * is not specified. </p> * * <p> The invocation of this method, and the subsequent use of the * resulting map, may cause time-consuming disk or network I/O operations * to occur. This method is provided for applications that need to * enumerate all of the available charsets, for example to allow user * charset selection. This method is not used by the {@link #forName * forName} method, which instead employs an efficient incremental lookup * algorithm. * * <p> This method may return different results at different times if new * charset providers are dynamically made available to the current Java * virtual machine. In the absence of such changes, the charsets returned * by this method are exactly those that can be retrieved via the {@link * #forName forName} method. </p> * * @return An immutable, case-insensitive map from canonical charset names * to charset objects */ public static SortedMap availableCharsets() { return (SortedMap)AccessController .doPrivileged(new PrivilegedAction() { public Object run() { TreeMap m = new TreeMap(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); put(standardProvider.charsets(), m); for (Iterator i = providers(); i.hasNext();) { CharsetProvider cp = (CharsetProvider)i.next(); put(cp.charsets(), m); } return Collections.unmodifiableSortedMap(m); } }); } /* -- Instance fields and methods -- */ private final String name; // tickles a bug in oldjavac private final String[] aliases; // tickles a bug in oldjavac private Set aliasSet = null; /** * Initializes a new charset with the given canonical name and alias * set. </p> * * @param canonicalName * The canonical name of this charset * * @param aliases * An array of this charset's aliases, or null if it has no aliases * * @throws IllegalCharsetNameException * If the canonical name or any of the aliases are illegal */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -