Charset.java revision c89c180eb85cc0392c3a6c2eb4803594478e665c
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.nio.charset; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughesimport com.ibm.icu4jni.charset.NativeConverter; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.BufferedReader; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStreamReader; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URL; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.ByteBuffer; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.CharBuffer; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.charset.spi.CharsetProvider; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.AccessController; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PrivilegedAction; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Collections; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Comparator; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Enumeration; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.HashMap; 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.HashSet; 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Iterator; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Locale; 38bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughesimport java.util.Map; 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Set; 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.SortedMap; 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.TreeMap; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 44c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * A charset is a named mapping between Unicode characters and byte sequences. Every 45c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * {@code Charset} can <i>decode</i>, converting a byte sequence into a sequence of characters, 46c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * and some can also <i>encode</i>, converting a sequence of characters into a byte sequence. 47c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * Use the method {@link #canEncode} to find out whether a charset supports both. 48c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * 49c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <h4>Characters</h4> 50c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>In the context of this class, <i>character</i> always refers to a Java character: a Unicode 51c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * code point in the range U+0000 to U+FFFF. (Java represents supplementary characters using surrogates.) 52c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * Not all byte sequences will represent a character, and not 53c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * all characters can necessarily be represented by a given charset. The method {@link #contains} 54c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * can be used to determine whether every character representable by one charset can also be 55c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * represented by another (meaning that a lossless transformation is possible from the contained 56c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * to the container). 57c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * 58c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <h4>Encodings</h4> 59c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>There are many possible ways to represent Unicode characters as byte sequences. 60c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * See <a href="http://www.unicode.org/reports/tr17/">UTR#17: Unicode Character Encoding Model</a> 61c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * for detailed discussion. 62c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 63c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>The most important mappings capable of representing every character are the Unicode 64c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * Transformation Format (UTF) charsets. Of those, UTF-8 and the UTF-16 family are the most 65c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * common. UTF-8 (described in <a href="http://www.ietf.org/rfc/rfc3629.txt">RFC 3629</a>) 66c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * encodes a character using 1 to 4 bytes. UTF-16 uses exactly 2 bytes per character (potentially 67c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * wasting space, but allowing efficient random access into BMP text), and UTF-32 uses 68c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * exactly 4 bytes per character (trading off even more space for efficient random access into text 69c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * that includes supplementary characters). 70c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 71c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>UTF-16 and UTF-32 encode characters directly, using their code point as a two- or four-byte 72c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * integer. This means that any given UTF-16 or UTF-32 byte sequence is either big- or 73c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * little-endian. To assist decoders, Unicode includes a special <i>byte order mark</i> (BOM) 74c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * character U+FEFF used to determine the endianness of a sequence. The corresponding byte-swapped 75c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * code point U+FFFE is guaranteed never to be assigned. If a UTF-16 decoder sees 76c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * {@code 0xfe, 0xff}, for example, it knows it's reading a big-endian byte sequence, while 77c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * {@code 0xff, 0xfe}, would indicate a little-endian byte sequence. 78c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 79c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>UTF-8 can contain a BOM, but since the UTF-8 encoding of a character always uses the same 80c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * byte sequence, there is no information about endianness to convey. Seeing the bytes 81c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * corresponding to the UTF-8 encoding of U+FEFF ({@code 0xef, 0xbb, 0xbf}) would only serve to 82c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * suggest that you're reading UTF-8. Note that BOMs are decoded as the U+FEFF character, and 83c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * will appear in the output character sequence. This means that a disadvantage to including a BOM 84c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * in UTF-8 is that most applications that use UTF-8 do not expect to see a BOM. (This is also a 85c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * reason to prefer UTF-8: it's one less complication to worry about.) 86c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 87c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>Because a BOM indicates how the data that follows should be interpreted, a BOM should occur 88c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * as the first character in a character sequence. 89c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 90c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>See the <a href="http://unicode.org/faq/utf_bom.html#BOM">Byte Order Mark (BOM) FAQ</a> for 91c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * more about dealing with BOMs. 92c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 93c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <h4>Endianness and BOM behavior</h4> 94c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 95c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>The following tables show the endianness and BOM behavior of the UTF-16 variants. 96c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 97c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>This table shows what the encoder writes. "BE" means that the byte sequence is big-endian, 98c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * "LE" means little-endian. "BE BOM" means a big-endian BOM (that is, {@code 0xfe, 0xff}). 99c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p><table width="100%"> 100c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <tr> <th>Charset</th> <th>Encoder writes</th> </tr> 101c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <tr> <td>UTF-16BE</td> <td>BE, no BOM</td> </tr> 102c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <tr> <td>UTF-16LE</td> <td>LE, no BOM</td> </tr> 103c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <tr> <td>UTF-16</td> <td>BE, with BE BOM</td> </tr> 104c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * </table> 105c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 106c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>The next table shows how each variant's decoder behaves when reading a byte sequence. 107c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * The exact meaning of "failure" in the table is dependent on the 108c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * {@link CodingErrorAction} supplied to {@link CharsetDecoder#malformedInputAction}, so 109c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * "BE, failure" means "the byte sequence is treated as big-endian, and a little-endian BOM 110c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * triggers the malformedInputAction". 111c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 112c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>The phrase "includes BOM" means that the output includes the U+FEFF byte order mark character. 113c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 114c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p><table width="100%"> 115c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <tr> <th>Charset</th> <th>BE BOM</th> <th>LE BOM</th> <th>No BOM</th> </tr> 116c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <tr> <td>UTF-16BE</td> <td>BE, includes BOM</td> <td>BE, failure</td> <td>BE</td> </tr> 117c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <tr> <td>UTF-16LE</td> <td>LE, failure</td> <td>LE, includes BOM</td> <td>LE</td> </tr> 118c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <tr> <td>UTF-16</td> <td>BE, includes BOM</td> <td>LE, includes BOM</td> <td>BE</td> </tr> 119c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * </table> 120c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 121c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <h4>Charset names</h4> 122c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>A charset has a canonical name, returned by {@link #name}. Most charsets will 123c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * also have one or more aliases, returned by {@link #aliases}. A charset can be looked up 124c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * by canonical name or any of its aliases using {@link #forName}. 125c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 126c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <h4>Guaranteed-available charsets</h4> 127c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>The following charsets are available on every Java implementation: 128c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * <ul> 129c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * <li>ISO-8859-1 130c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * <li>US-ASCII 131c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * <li>UTF-16 132c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * <li>UTF-16BE 133c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * <li>UTF-16LE 134c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * <li>UTF-8 135c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * </ul> 136c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>All of these charsets support both decoding and encoding. The charsets whose names begin 137c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * "UTF" can represent all characters, as mentioned above. The "ISO-8859-1" and "US-ASCII" charsets 138c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * can only represent small subsets of these characters. Except when required to do otherwise for 139c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * compatibility, new code should use one of the UTF charsets listed above. The platform's default 140c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * charset is UTF-8. (This is in contrast to some older implementations, where the default charset 141c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * depended on the user's locale.) 142c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 143c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>Most implementations will support hundreds of charsets. Use {@link #availableCharsets} or 144c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * {@link #isSupported} to see what's available. If you intend to use the charset if it's 145c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * available, just call {@link #forName} and catch the exceptions it throws if the charset isn't 146c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * available. 147c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * 148c60bc1815dca549f3fb4e572f6aac749d7fa9fc6Elliott Hughes * <p>Additional charsets can be made available by configuring one or more charset 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * providers through provider configuration files. Such files are always named 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * as "java.nio.charset.spi.CharsetProvider" and located in the 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * "META-INF/services" sub folder of one or more classpaths. The files should be 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encoded in "UTF-8". Each line of their content specifies the class name of a 153c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * charset provider which extends {@link java.nio.charset.spi.CharsetProvider}. 154c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * A line should end with '\r', '\n' or '\r\n'. Leading and trailing whitespaces 155c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * are trimmed. Blank lines, and lines (after trimming) starting with "#" which are 156c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * regarded as comments, are both ignored. Duplicates of names already found are also 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ignored. Both the configuration files and the provider classes will be loaded 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * using the thread context class loader. 159eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 160c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>Although class is thread-safe, the {@link CharsetDecoder} and {@link CharsetEncoder} instances 161c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * it returns are inherently stateful. 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic abstract class Charset implements Comparable<Charset> { 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 165eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * The name of configuration files where charset provider class names can be 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified. 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 168f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private static final String PROVIDER_CONFIGURATION_FILE_NAME = "META-INF/services/java.nio.charset.spi.CharsetProvider"; 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 171eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * The encoding of configuration files 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 173f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private static final String PROVIDER_CONFIGURATION_FILE_ENCODING = "UTF-8"; 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 176eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * The comment string used in configuration files 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 178f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private static final String PROVIDER_CONFIGURATION_FILE_COMMENT = "#"; 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static ClassLoader systemClassLoader; 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 182ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes private static SortedMap<String, Charset> cachedBuiltInCharsets; 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final String canonicalName; 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // the aliases set 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final HashSet<String> aliasesSet; 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // cached Charset table 190eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private final static HashMap<String, Charset> cachedCharsetTable = new HashMap<String, Charset>(); 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 192eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private static boolean inForNameInternal = false; 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a <code>Charset</code> object. Duplicated aliases are 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ignored. 197f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param canonicalName 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the canonical name of the charset. 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param aliases 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * an array containing all aliases of the charset. May be null. 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalCharsetNameException 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * on an illegal value being supplied for either 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>canonicalName</code> or for any element of 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <code>aliases</code>. 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 207eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson protected Charset(String canonicalName, String[] aliases) { 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (null == canonicalName) { 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new NullPointerException(); 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check whether the given canonical name is legal 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project checkCharsetName(canonicalName); 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.canonicalName = canonicalName; 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // check each alias and put into a set 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.aliasesSet = new HashSet<String>(); 216bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (aliases != null) { 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < aliases.length; i++) { 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project checkCharsetName(aliases[i]); 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.aliasesSet.add(aliases[i]); 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Checks whether a character is a special character that can be used in 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * charset names, other than letters and digits. 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static boolean isSpecial(char c) { 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ('-' == c || '.' == c || ':' == c || '_' == c); 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Checks whether a character is a letter (ascii) which are defined in the 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * spec. 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static boolean isLetter(char c) { 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Checks whether a character is a digit (ascii) which are defined in the 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * spec. 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static boolean isDigit(char c) { 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ('0' <= c && c <= '9'); 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Checks whether a given string is a legal charset name. The argument name 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * should not be null. 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static void checkCharsetName(String name) { 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // An empty string is illegal charset name 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (name.length() == 0) { 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalCharsetNameException(name); 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // The first character must be a letter or a digit 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // This is related to HARMONY-68 (won't fix) 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // char first = name.charAt(0); 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // if (!isLetter(first) && !isDigit(first)) { 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // throw new IllegalCharsetNameException(name); 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // } 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Check the remaining characters 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int length = name.length(); 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (int i = 0; i < length; i++) { 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char c = name.charAt(i); 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!isLetter(c) && !isDigit(c) && !isSpecial(c)) { 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalCharsetNameException(name); 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Use privileged code to get the context class loader. 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static ClassLoader getContextClassLoader() { 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project final Thread t = Thread.currentThread(); 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return AccessController 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .doPrivileged(new PrivilegedAction<ClassLoader>() { 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public ClassLoader run() { 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return t.getContextClassLoader(); 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project }); 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Use privileged code to get the system class loader. 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static void getSystemClassLoader() { 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (null == systemClassLoader) { 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project systemClassLoader = AccessController 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .doPrivileged(new PrivilegedAction<ClassLoader>() { 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public ClassLoader run() { 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ClassLoader.getSystemClassLoader(); 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project }); 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Add the charsets supported by the given provider to the map. 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 303bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes private static void addCharsets(CharsetProvider cp, Map<String, Charset> charsets) { 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Iterator<Charset> it = cp.charsets(); 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (it.hasNext()) { 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Charset cs = it.next(); 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Only new charsets will be added 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!charsets.containsKey(cs.name())) { 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project charsets.put(cs.name(), cs); 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Trim comment string, and then trim white spaces. 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static String trimClassName(String name) { 318c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes String trimmedName = name; 319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int index = name.indexOf(PROVIDER_CONFIGURATION_FILE_COMMENT); 320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Trim comments 321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (index != -1) { 322c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes trimmedName = name.substring(0, index); 323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 324c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes return trimmedName.trim(); 325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Read a configuration file and add the charsets supported by the providers 329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * specified by this configuration file to the map. 330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static void loadConfiguredCharsets(URL configFile, 332bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes ClassLoader contextClassLoader, Map<String, Charset> charsets) { 333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project BufferedReader reader = null; 334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InputStream is = configFile.openStream(); 336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Read each line for charset provider class names 337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reader = new BufferedReader(new InputStreamReader(is, 338b748a9b827665a8b19d60af4b419503b45e74329Elliott Hughes PROVIDER_CONFIGURATION_FILE_ENCODING)); 339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String providerClassName = reader.readLine(); 340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (null != providerClassName) { 341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project providerClassName = trimClassName(providerClassName); 342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Skip comments and blank lines 343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (providerClassName.length() > 0) { // Non empty string 344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Load the charset provider 345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object cp = null; 346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Class<?> c = Class.forName(providerClassName, true, 348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contextClassLoader); 349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cp = c.newInstance(); 350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception ex) { 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // try to use system classloader when context 352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // classloader failed to load config file. 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project getSystemClassLoader(); 355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Class<?> c = Class.forName(providerClassName, true, 356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project systemClassLoader); 357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cp = c.newInstance(); 358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new Error(e.getMessage(), e); 360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Put the charsets supported by this provider into the map 363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project addCharsets((CharsetProvider) cp, charsets); 364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Read the next line of the config file 366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project providerClassName = reader.readLine(); 367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException ex) { 369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Can't read this configuration file, ignore 370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (null != reader) { 373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reader.close(); 374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException ex) { 376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Ignore closing exception 377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 381ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes private static synchronized SortedMap<String, Charset> getCachedBuiltInCharsets() { 382ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes if (cachedBuiltInCharsets == null) { 383ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes cachedBuiltInCharsets = new TreeMap<String, Charset>(String.CASE_INSENSITIVE_ORDER); 384ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes for (String charsetName : NativeConverter.getAvailableCharsetNames()) { 385ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes Charset charset = NativeConverter.charsetForName(charsetName); 386ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes cachedBuiltInCharsets.put(charset.name(), charset); 387ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes } 388ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes } 389ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes return cachedBuiltInCharsets; 390ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes } 391ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes 392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 393ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes * Returns an immutable case-insensitive map from canonical names to {@code Charset} instances. 394ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes * If multiple charsets have the same canonical name, it is unspecified which is returned in 395ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes * the map. This method may be slow. If you know which charset you're looking for, use 396ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes * {@link #forName}. 397ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes * @return an immutable case-insensitive map from canonical names to {@code Charset} instances 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @SuppressWarnings("unchecked") 400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static SortedMap<String, Charset> availableCharsets() { 401ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes // Start with a copy of the built-in charsets... 402ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes TreeMap<String, Charset> charsets = new TreeMap<String, Charset>(String.CASE_INSENSITIVE_ORDER); 403ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes charsets.putAll(getCachedBuiltInCharsets()); 404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 405bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes // Add all charsets provided by charset providers... 406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ClassLoader contextClassLoader = getContextClassLoader(); 407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Enumeration<URL> e = null; 408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 409bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (contextClassLoader != null) { 410bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes e = contextClassLoader.getResources(PROVIDER_CONFIGURATION_FILE_NAME); 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project getSystemClassLoader(); 413bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes e = systemClassLoader.getResources(PROVIDER_CONFIGURATION_FILE_NAME); 414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Examine each configuration file 416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (e.hasMoreElements()) { 417bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes loadConfiguredCharsets(e.nextElement(), contextClassLoader, charsets); 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException ex) { 420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Unexpected ClassLoader exception, ignore 421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Collections.unmodifiableSortedMap(charsets); 423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Read a configuration file and try to find the desired charset among those 427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * which are supported by the providers specified in this configuration 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * file. 429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private static Charset searchConfiguredCharsets(String charsetName, 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ClassLoader contextClassLoader, URL configFile) { 432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project BufferedReader reader = null; 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project InputStream is = configFile.openStream(); 435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Read each line for charset provider class names 436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reader = new BufferedReader(new InputStreamReader(is, 437b748a9b827665a8b19d60af4b419503b45e74329Elliott Hughes PROVIDER_CONFIGURATION_FILE_ENCODING)); 438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String providerClassName = reader.readLine(); 439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while (null != providerClassName) { 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project providerClassName = trimClassName(providerClassName); 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (providerClassName.length() > 0) { // Non empty string 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Load the charset provider 443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object cp = null; 444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Class<?> c = Class.forName(providerClassName, true, 446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project contextClassLoader); 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cp = c.newInstance(); 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception ex) { 449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // try to use system classloader when context 450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // classloader failed to load config file. 451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project getSystemClassLoader(); 453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Class<?> c = Class.forName(providerClassName, true, 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project systemClassLoader); 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cp = c.newInstance(); 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (SecurityException e) { 457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // BEGIN android-changed 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // ignore 459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // END android-changed 460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Exception e) { 461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new Error(e.getMessage(), e); 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // BEGIN android-changed 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (cp != null) { 466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Try to get the desired charset from this provider 467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Charset cs = ((CharsetProvider) cp) 468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .charsetForName(charsetName); 469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (null != cs) { 470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return cs; 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // END android-changed 474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Read the next line of the config file 476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project providerClassName = reader.readLine(); 477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException ex) { 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Can't read this configuration file 481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (null != reader) { 485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project reader.close(); 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException ex) { 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Ignore closing exception 489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 494eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * Gets a <code>Charset</code> instance for the specified charset name. If 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the charset is not supported, returns null instead of throwing an 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * exception. 497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 498eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson private synchronized static Charset forNameInternal(String charsetName) 499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throws IllegalCharsetNameException { 500eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 501bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes Charset cs = lookupCachedOrBuiltInCharset(charsetName); 502bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (cs != null || inForNameInternal) { 503eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson return cs; 504eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 506eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson // collect all charsets provided by charset providers 507eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson try { 508bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes Enumeration<URL> e = null; 509bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes ClassLoader contextClassLoader = getContextClassLoader(); 510bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (contextClassLoader != null) { 511bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes e = contextClassLoader.getResources(PROVIDER_CONFIGURATION_FILE_NAME); 512eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } else { 513eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson getSystemClassLoader(); 514eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson if (systemClassLoader == null) { 515eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson // Non available during class library start-up phase 516bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return null; 517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 518bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes e = systemClassLoader.getResources(PROVIDER_CONFIGURATION_FILE_NAME); 519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 520eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 521eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson 522eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson // examine each configuration file 523eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson while (e.hasMoreElements()) { 524bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes inForNameInternal = true; 525bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes cs = searchConfiguredCharsets(charsetName, contextClassLoader, e.nextElement()); 526bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes inForNameInternal = false; 527bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (cs != null) { 528eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson cacheCharset(cs); 529eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson return cs; 530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 532eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } catch (IOException ex) { 533eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson // Unexpected ClassLoader exception, ignore 534eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } finally { 535bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes inForNameInternal = false; 536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 540bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes private synchronized static Charset lookupCachedOrBuiltInCharset(String charsetName) { 541bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes Charset cs = cachedCharsetTable.get(charsetName); 542bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (cs != null) { 543bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return cs; 544bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes } 545bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (charsetName == null) { 546bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes throw new IllegalArgumentException(); 547bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes } 548bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes checkCharsetName(charsetName); 549ccb8b92211a3e87acaf6486c8d4423c2053b8b5eElliott Hughes cs = NativeConverter.charsetForName(charsetName); 550bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (cs != null) { 551bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes cacheCharset(cs); 552bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes } 553bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return cs; 554bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes } 555bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes 556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * save charset into cachedCharsetTable 558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 559bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes private synchronized static void cacheCharset(Charset cs) { 560bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes // Cache the Charset by its canonical name... 561bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes String canonicalName = cs.name(); 562bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (!cachedCharsetTable.containsKey(canonicalName)) { 563bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes cachedCharsetTable.put(canonicalName, cs); 564eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson } 565bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes // And all its aliases... 566bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes for (String alias : cs.aliasesSet) { 567bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (!cachedCharsetTable.containsKey(alias)) { 568bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes cachedCharsetTable.put(alias, cs); 569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets a <code>Charset</code> instance for the specified charset name. 575f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param charsetName 577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the canonical name of the charset or an alias. 578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a <code>Charset</code> instance for the specified charset name. 579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalCharsetNameException 580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the specified charset name is illegal. 581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws UnsupportedCharsetException 582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the desired charset is not supported by this runtime. 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 584eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson public static Charset forName(String charsetName) { 585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Charset c = forNameInternal(charsetName); 586bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes if (c == null) { 587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new UnsupportedCharsetException(charsetName); 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return c; 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Determines whether the specified charset is supported by this runtime. 594f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param charsetName 596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the name of the charset. 597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if the specified charset is supported, otherwise false. 598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalCharsetNameException 599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the specified charset name is illegal. 600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 601eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson public static synchronized boolean isSupported(String charsetName) { 602bcf7c66e617ad0c33bb320184bb2401def517342Elliott Hughes return forNameInternal(charsetName) != null; 603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 606c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * Determines whether this charset is a superset of the given charset. A charset C1 contains 607c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * charset C2 if every character representable by C2 is also representable by C1. This means 608c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * that lossless conversion is possible from C2 to C1 (but not necessarily the other way 609c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * round). It does <i>not</i> imply that the two charsets use the same byte sequences for the 610c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * characters they share. 611c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 612c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>Note that this method is allowed to be conservative, and some implementations may return 613c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * false when this charset does contain the other charset. Android's implementation is precise, 614c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * and will always return true in such cases. 615f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param charset 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a given charset. 618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if this charset is a super set of the given charset, 619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * false if it's unknown or this charset is not a superset of 620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given charset. 621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public abstract boolean contains(Charset charset); 623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets a new instance of an encoder for this charset. 626f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a new instance of an encoder for this charset. 628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public abstract CharsetEncoder newEncoder(); 630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets a new instance of a decoder for this charset. 633f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a new instance of a decoder for this charset. 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public abstract CharsetDecoder newDecoder(); 637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the canonical name of this charset. 640f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return this charset's name in canonical form. 642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final String name() { 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this.canonicalName; 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the set of this charset's aliases. 649f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return an unmodifiable set of this charset's aliases. 651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final Set<String> aliases() { 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Collections.unmodifiableSet(this.aliasesSet); 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the name of this charset for the default locale. 658f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 659eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * <p>The default implementation returns the canonical name of this charset. 660eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * Subclasses may return a localized display name. 661eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the name of this charset for the default locale. 663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String displayName() { 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this.canonicalName; 666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the name of this charset for the specified locale. 670eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 671eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * <p>The default implementation returns the canonical name of this charset. 672eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * Subclasses may return a localized display name. 673eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param l 675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a certain locale 676eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * @return the name of this charset for the specified locale 677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String displayName(Locale l) { 679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this.canonicalName; 680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Indicates whether this charset is known to be registered in the IANA 684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Charset Registry. 685f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if the charset is known to be registered, otherwise returns 687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * false. 688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final boolean isRegistered() { 690f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes return !canonicalName.startsWith("x-") 691f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes && !canonicalName.startsWith("X-"); 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns true if this charset supports encoding, false otherwise. 696f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if this charset supports encoding, false otherwise. 698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean canEncode() { 700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 704c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * Returns a new {@code ByteBuffer} containing the bytes encoding the characters from 705c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * {@code buffer}. 706c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * This method uses {@code CodingErrorAction.REPLACE}. 707c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 708c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>Applications should generally create a {@link CharsetEncoder} using {@link #newEncoder} 709c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * for performance. 710eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param buffer 712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the character buffer containing the content to be encoded. 713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the result of the encoding. 714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 715eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson public final ByteBuffer encode(CharBuffer buffer) { 716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 717c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes return newEncoder() 718eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson .onMalformedInput(CodingErrorAction.REPLACE) 719eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson .onUnmappableCharacter(CodingErrorAction.REPLACE).encode( 720eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson buffer); 721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (CharacterCodingException ex) { 722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new Error(ex.getMessage(), ex); 723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 727c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * Returns a new {@code ByteBuffer} containing the bytes encoding the characters from {@code s}. 728c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * This method uses {@code CodingErrorAction.REPLACE}. 729eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson * 730c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>Applications should generally create a {@link CharsetEncoder} using {@link #newEncoder} 731c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * for performance. 732c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 733c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * @param s the string to be encoded. 734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the result of the encoding. 735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final ByteBuffer encode(String s) { 737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return encode(CharBuffer.wrap(s)); 738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 741c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * Returns a new {@code CharBuffer} containing the characters decoded from {@code buffer}. 742c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * This method uses {@code CodingErrorAction.REPLACE}. 743c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * 744c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * <p>Applications should generally create a {@link CharsetDecoder} using {@link #newDecoder} 745c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * for performance. 746f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param buffer 748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the byte buffer containing the content to be decoded. 749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a character buffer containing the output of the decoding. 750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final CharBuffer decode(ByteBuffer buffer) { 752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 753c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes return newDecoder() 754eaa2ff09069424b0f7a95c7cd831cef1b744fe67Jesse Wilson .onMalformedInput(CodingErrorAction.REPLACE) 755c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes .onUnmappableCharacter(CodingErrorAction.REPLACE).decode(buffer); 756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (CharacterCodingException ex) { 757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new Error(ex.getMessage(), ex); 758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ------------------------------------------------------------------- 763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Methods implementing parent interface Comparable 764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ------------------------------------------------------------------- 765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 768c89c180eb85cc0392c3a6c2eb4803594478e665cElliott Hughes * Compares this charset with the given charset. This comparison is 769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * based on the case insensitive canonical names of the charsets. 770f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param charset 772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given object to be compared with. 773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a negative integer if less than the given object, a positive 774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * integer if larger than it, or 0 if equal to it. 775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int compareTo(Charset charset) { 777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this.canonicalName.compareToIgnoreCase(charset.canonicalName); 778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ------------------------------------------------------------------- 782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Methods overriding parent class Object 783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ------------------------------------------------------------------- 784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Determines whether this charset equals to the given object. They are 788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * considered to be equal if they have the same canonical name. 789f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param obj 791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the given object to be compared with. 792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return true if they have the same canonical name, otherwise false. 793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final boolean equals(Object obj) { 796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (obj instanceof Charset) { 797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Charset that = (Charset) obj; 798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this.canonicalName.equals(that.canonicalName); 799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the hash code of this charset. 805f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the hash code of this charset. 807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final int hashCode() { 810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return this.canonicalName.hashCode(); 811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets a string representation of this charset. Usually this contains the 815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * canonical name of the charset. 816f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a string representation of this charset. 818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final String toString() { 821f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes return "Charset[" + this.canonicalName + "]"; 822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the system default charset from the virtual machine. 826f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the default charset. 828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static Charset defaultCharset() { 830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Charset defaultCharset = null; 831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String encoding = AccessController 832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project .doPrivileged(new PrivilegedAction<String>() { 833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String run() { 834f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes return System.getProperty("file.encoding"); 835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project }); 837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project defaultCharset = Charset.forName(encoding); 839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (UnsupportedCharsetException e) { 840f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes defaultCharset = Charset.forName("UTF-8"); 841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return defaultCharset; 843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 845