KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > nio > charset > Charset


1 /*
2  * @(#)Charset.java 1.47 04/08/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.nio.charset;
9
10 import java.nio.ByteBuffer JavaDoc;
11 import java.nio.CharBuffer JavaDoc;
12 import java.nio.charset.spi.CharsetProvider JavaDoc;
13 import java.security.AccessController JavaDoc;
14 import java.security.AccessControlException JavaDoc;
15 import java.security.PrivilegedAction JavaDoc;
16 import java.util.Collections JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.Locale JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.NoSuchElementException JavaDoc;
22 import java.util.Set JavaDoc;
23 import java.util.SortedMap JavaDoc;
24 import java.util.TreeMap JavaDoc;
25 import sun.misc.ASCIICaseInsensitiveComparator;
26 import sun.misc.Service;
27 import sun.misc.ServiceConfigurationError;
28 import sun.nio.cs.StandardCharsets;
29 import sun.nio.cs.ThreadLocalCoders;
30 import sun.security.action.GetPropertyAction;
31
32
33 /**
34  * A named mapping between sequences of sixteen-bit Unicode <a
35  * HREF="../../lang/Character.java#unicode">code units</a> and sequences of
36  * bytes. This class defines methods for creating decoders and encoders and
37  * for retrieving the various names associated with a charset. Instances of
38  * this class are immutable.
39  *
40  * <p> This class also defines static methods for testing whether a particular
41  * charset is supported, for locating charset instances by name, and for
42  * constructing a map that contains every charset for which support is
43  * available in the current Java virtual machine. Support for new charsets can
44  * be added via the service-provider interface defined in the {@link
45  * java.nio.charset.spi.CharsetProvider} class.
46  *
47  * <p> All of the methods defined in this class are safe for use by multiple
48  * concurrent threads.
49  *
50  *
51  * <a name="names"><a name="charenc">
52  * <h4>Charset names</h4>
53  *
54  * <p> Charsets are named by strings composed of the following characters:
55  *
56  * <ul>
57  *
58  * <li> The uppercase letters <tt>'A'</tt> through <tt>'Z'</tt>
59  * (<tt>'&#92;u0041'</tt>&nbsp;through&nbsp;<tt>'&#92;u005a'</tt>),
60  *
61  * <li> The lowercase letters <tt>'a'</tt> through <tt>'z'</tt>
62  * (<tt>'&#92;u0061'</tt>&nbsp;through&nbsp;<tt>'&#92;u007a'</tt>),
63  *
64  * <li> The digits <tt>'0'</tt> through <tt>'9'</tt>
65  * (<tt>'&#92;u0030'</tt>&nbsp;through&nbsp;<tt>'&#92;u0039'</tt>),
66  *
67  * <li> The dash character <tt>'-'</tt>
68  * (<tt>'&#92;u002d'</tt>,&nbsp;<small>HYPHEN-MINUS</small>),
69  *
70  * <li> The period character <tt>'.'</tt>
71  * (<tt>'&#92;u002e'</tt>,&nbsp;<small>FULL STOP</small>),
72  *
73  * <li> The colon character <tt>':'</tt>
74  * (<tt>'&#92;u003a'</tt>,&nbsp;<small>COLON</small>), and
75  *
76  * <li> The underscore character <tt>'_'</tt>
77  * (<tt>'&#92;u005f'</tt>,&nbsp;<small>LOW&nbsp;LINE</small>).
78  *
79  * </ul>
80  *
81  * A charset name must begin with either a letter or a digit. The empty string
82  * is not a legal charset name. Charset names are not case-sensitive; that is,
83  * case is always ignored when comparing charset names. Charset names
84  * generally follow the conventions documented in <a
85  * HREF="http://ietf.org/rfc/rfc2278.txt"><i>RFC&nbsp;2278:&nbsp;IANA Charset
86  * Registration Procedures</i></a>.
87  *
88  * <p> Every charset has a <i>canonical name</i> and may also have one or more
89  * <i>aliases</i>. The canonical name is returned by the {@link #name name} method
90  * of this class. Canonical names are, by convention, usually in upper case.
91  * The aliases of a charset are returned by the {@link #aliases aliases}
92  * method.
93  *
94  * <a name="hn">
95  *
96  * <p> Some charsets have an <i>historical name</i> that is defined for
97  * compatibility with previous versions of the Java platform. A charset's
98  * historical name is either its canonical name or one of its aliases. The
99  * historical name is returned by the <tt>getEncoding()</tt> methods of the
100  * {@link java.io.InputStreamReader#getEncoding InputStreamReader} and {@link
101  * java.io.OutputStreamWriter#getEncoding OutputStreamWriter} classes.
102  *
103  * <a name="iana">
104  *
105  * <p> If a charset listed in the <a
106  * HREF="http://www.iana.org/assignments/character-sets"><i>IANA Charset
107  * Registry</i></a> is supported by an implementation of the Java platform then
108  * its canonical name must be the name listed in the registry. Many charsets
109  * are given more than one name in the registry, in which case the registry
110  * identifies one of the names as <i>MIME-preferred</i>. If a charset has more
111  * than one registry name then its canonical name must be the MIME-preferred
112  * name and the other names in the registry must be valid aliases. If a
113  * supported charset is not listed in the IANA registry then its canonical name
114  * must begin with one of the strings <tt>"X-"</tt> or <tt>"x-"</tt>.
115  *
116  * <p> The IANA charset registry does change over time, and so the canonical
117  * name and the aliases of a particular charset may also change over time. To
118  * ensure compatibility it is recommended that no alias ever be removed from a
119  * charset, and that if the canonical name of a charset is changed then its
120  * previous canonical name be made into an alias.
121  *
122  *
123  * <h4>Standard charsets</h4>
124  *
125  * <p> Every implementation of the Java platform is required to support the
126  * following standard charsets. Consult the release documentation for your
127  * implementation to see if any other charsets are supported. The behavior
128  * of such optional charsets may differ between implementations.
129  *
130  * <blockquote><table width="80%" summary="Description of standard charsets">
131  * <tr><th><p align="left">Charset</p></th><th><p align="left">Description</p></th></tr>
132  * <tr><td valign=top><tt>US-ASCII</tt></td>
133  * <td>Seven-bit ASCII, a.k.a. <tt>ISO646-US</tt>,
134  * a.k.a. the Basic Latin block of the Unicode character set</td></tr>
135  * <tr><td valign=top><tt>ISO-8859-1&nbsp;&nbsp;</tt></td>
136  * <td>ISO Latin Alphabet No. 1, a.k.a. <tt>ISO-LATIN-1</tt></td></tr>
137  * <tr><td valign=top><tt>UTF-8</tt></td>
138  * <td>Eight-bit UCS Transformation Format</td></tr>
139  * <tr><td valign=top><tt>UTF-16BE</tt></td>
140  * <td>Sixteen-bit UCS Transformation Format,
141  * big-endian byte&nbsp;order</td></tr>
142  * <tr><td valign=top><tt>UTF-16LE</tt></td>
143  * <td>Sixteen-bit UCS Transformation Format,
144  * little-endian byte&nbsp;order</td></tr>
145  * <tr><td valign=top><tt>UTF-16</tt></td>
146  * <td>Sixteen-bit UCS Transformation Format,
147  * byte&nbsp;order identified by an optional byte-order mark</td></tr>
148  * </table></blockquote>
149  *
150  * <p> The <tt>UTF-8</tt> charset is specified by <a
151  * HREF="http://ietf.org/rfc/rfc2279.txt"><i>RFC&nbsp;2279</i></a>; the
152  * transformation format upon which it is based is specified in
153  * Amendment&nbsp;2 of ISO&nbsp;10646-1 and is also described in the <a
154  * HREF="http://www.unicode.org/unicode/standard/standard.html"><i>Unicode
155  * Standard</i></a>.
156  *
157  * <p> The <tt>UTF-16</tt> charsets are specified by <a
158  * HREF="http://ietf.org/rfc/rfc2781.txt"><i>RFC&nbsp;2781</i></a>; the
159  * transformation formats upon which they are based are specified in
160  * Amendment&nbsp;1 of ISO&nbsp;10646-1 and are also described in the <a
161  * HREF="http://www.unicode.org/unicode/standard/standard.html"><i>Unicode
162  * Standard</i></a>.
163  *
164  * <p> The <tt>UTF-16</tt> charsets use sixteen-bit quantities and are
165  * therefore sensitive to byte order. In these encodings the byte order of a
166  * stream may be indicated by an initial <i>byte-order mark</i> represented by
167  * the Unicode character <tt>'&#92;uFEFF'</tt>. Byte-order marks are handled
168  * as follows:
169  *
170  * <ul>
171  *
172  * <li><p> When decoding, the <tt>UTF-16BE</tt> and <tt>UTF-16LE</tt>
173  * charsets ignore byte-order marks; when encoding, they do not write
174  * byte-order marks. </p></li>
175  *
176  * <li><p> When decoding, the <tt>UTF-16</tt> charset interprets a byte-order
177  * mark to indicate the byte order of the stream but defaults to big-endian
178  * if there is no byte-order mark; when encoding, it uses big-endian byte
179  * order and writes a big-endian byte-order mark. </p></li>
180  *
181  * </ul>
182  *
183  * In any case, when a byte-order mark is read at the beginning of a decoding
184  * operation it is omitted from the resulting sequence of characters. Byte
185  * order marks occuring after the first element of an input sequence are not
186  * omitted since the same code is used to represent <small>ZERO-WIDTH
187  * NON-BREAKING SPACE</small>.
188  *
189  * <p> Every instance of the Java virtual machine has a default charset, which
190  * may or may not be one of the standard charsets. The default charset is
191  * determined during virtual-machine startup and typically depends upon the
192  * locale and charset being used by the underlying operating system. </p>
193  *
194  *
195  * <h4>Terminology</h4>
196  *
197  * <p> The name of this class is taken from the terms used in <a
198  * HREF="http://ietf.org/rfc/rfc2278.txt""><i>RFC&nbsp;2278</i></a>. In that
199  * document a <i>charset</i> is defined as the combination of a coded character
200  * set and a character-encoding scheme.
201  *
202  * <p> A <i>coded character set</i> is a mapping between a set of abstract
203  * characters and a set of integers. US-ASCII, ISO&nbsp;8859-1,
204  * JIS&nbsp;X&nbsp;0201, and full Unicode, which is the same as
205  * ISO&nbsp;10646-1, are examples of coded character sets.
206  *
207  * <p> A <i>character-encoding scheme</i> is a mapping between a coded
208  * character set and a set of octet (eight-bit byte) sequences. UTF-8, UCS-2,
209  * UTF-16, ISO&nbsp;2022, and EUC are examples of character-encoding schemes.
210  * Encoding schemes are often associated with a particular coded character set;
211  * UTF-8, for example, is used only to encode Unicode. Some schemes, however,
212  * are associated with multiple character sets; EUC, for example, can be used
213  * to encode characters in a variety of Asian character sets.
214  *
215  * <p> When a coded character set is used exclusively with a single
216  * character-encoding scheme then the corresponding charset is usually named
217  * for the character set; otherwise a charset is usually named for the encoding
218  * scheme and, possibly, the locale of the character sets that it supports.
219  * Hence <tt>US-ASCII</tt> is the name of the charset for US-ASCII while
220  * <tt>EUC-JP</tt> is the name of the charset that encodes the
221  * JIS&nbsp;X&nbsp;0201, JIS&nbsp;X&nbsp;0208, and JIS&nbsp;X&nbsp;0212
222  * character sets.
223  *
224  * <p> The native character encoding of the Java programming language is
225  * UTF-16. A charset in the Java platform therefore defines a mapping between
226  * sequences of sixteen-bit UTF-16 code units and sequences of bytes. </p>
227  *
228  *
229  * @author Mark Reinhold
230  * @author JSR-51 Expert Group
231  * @version 1.47, 04/08/19
232  * @since 1.4
233  *
234  * @see CharsetDecoder
235  * @see CharsetEncoder
236  * @see java.nio.charset.spi.CharsetProvider
237  * @see java.lang.Character
238  */

239
240 public abstract class Charset
241     implements Comparable JavaDoc<Charset JavaDoc>
242 {
243
244     /* -- Static methods -- */
245
246     private static String JavaDoc bugLevel = null;
247
248     static boolean atBugLevel(String JavaDoc bl) { // package-private
249
if (bugLevel == null) {
250         if (!sun.misc.VM.isBooted())
251         return false;
252         java.security.PrivilegedAction JavaDoc pa =
253         new GetPropertyAction("sun.nio.cs.bugLevel");
254         bugLevel = (String JavaDoc)AccessController.doPrivileged(pa);
255         if (bugLevel == null)
256         bugLevel = "";
257     }
258     return (bugLevel != null) && bugLevel.equals(bl);
259     }
260
261     /**
262      * Checks that the given string is a legal charset name. </p>
263      *
264      * @param s
265      * A purported charset name
266      *
267      * @throws IllegalCharsetNameException
268      * If the given name is not a legal charset name
269      */

270     private static void checkName(String JavaDoc s) {
271     int n = s.length();
272     if (!atBugLevel("1.4")) {
273         if (n == 0)
274         throw new IllegalCharsetNameException JavaDoc(s);
275     }
276     for (int i = 0; i < n; i++) {
277         char c = s.charAt(i);
278         if (c >= 'A' && c <= 'Z') continue;
279         if (c >= 'a' && c <= 'z') continue;
280         if (c >= '0' && c <= '9') continue;
281         if (c == '-') continue;
282         if (c == ':') continue;
283         if (c == '_') continue;
284         if (c == '.') continue;
285         throw new IllegalCharsetNameException JavaDoc(s);
286     }
287     }
288
289     /* The standard set of charsets */
290     private static CharsetProvider JavaDoc standardProvider = new StandardCharsets();
291
292     // Cache of the most-recently-returned charsets,
293
// along with the names that were used to find them
294
//
295
private static volatile Object JavaDoc[] cache1 = null; // "Level 1" cache
296
private static volatile Object JavaDoc[] cache2 = null; // "Level 2" cache
297

298     private static void cache(String JavaDoc charsetName, Charset JavaDoc cs) {
299     cache2 = cache1;
300     cache1 = new Object JavaDoc[] { charsetName, cs };
301     }
302
303     // Creates an iterator that walks over the available providers, ignoring
304
// those whose lookup or instantiation causes a security exception to be
305
// thrown. Should be invoked with full privileges.
306
//
307
private static Iterator JavaDoc providers() {
308     return new Iterator JavaDoc() {
309
310         Class JavaDoc c = java.nio.charset.spi.CharsetProvider JavaDoc.class;
311         ClassLoader JavaDoc cl = ClassLoader.getSystemClassLoader();
312         Iterator JavaDoc i = Service.providers(c, cl);
313         Object JavaDoc next = null;
314
315         private boolean getNext() {
316             while (next == null) {
317             try {
318                 if (!i.hasNext())
319                 return false;
320                 next = i.next();
321             } catch (ServiceConfigurationError sce) {
322                 if (sce.getCause() instanceof SecurityException JavaDoc) {
323                 // Ignore security exceptions
324
continue;
325                 }
326                 throw sce;
327             }
328             }
329             return true;
330         }
331
332         public boolean hasNext() {
333             return getNext();
334         }
335
336         public Object JavaDoc next() {
337             if (!getNext())
338             throw new NoSuchElementException JavaDoc();
339             Object JavaDoc n = next;
340             next = null;
341             return n;
342         }
343
344         public void remove() {
345             throw new UnsupportedOperationException JavaDoc();
346         }
347
348         };
349     }
350
351     // Thread-local gate to prevent recursive provider lookups
352
private static ThreadLocal JavaDoc gate = new ThreadLocal JavaDoc();
353
354     private static Charset JavaDoc lookupViaProviders(final String JavaDoc charsetName) {
355
356     // The runtime startup sequence looks up standard charsets as a
357
// consequence of the VM's invocation of System.initializeSystemClass
358
// in order to, e.g., set system properties and encode filenames. At
359
// that point the application class loader has not been initialized,
360
// however, so we can't look for providers because doing so will cause
361
// that loader to be prematurely initialized with incomplete
362
// information.
363
//
364
if (!sun.misc.VM.isBooted())
365         return null;
366
367     if (gate.get() != null)
368         // Avoid recursive provider lookups
369
return null;
370     try {
371         gate.set(gate);
372
373         return (Charset JavaDoc)AccessController
374         .doPrivileged(new PrivilegedAction JavaDoc() {
375             public Object JavaDoc run() {
376             for (Iterator JavaDoc i = providers(); i.hasNext();) {
377                 CharsetProvider JavaDoc cp = (CharsetProvider JavaDoc)i.next();
378                 Charset JavaDoc cs = cp.charsetForName(charsetName);
379                 if (cs != null)
380                 return cs;
381             }
382             return null;
383             }
384         });
385
386     } finally {
387         gate.set(null);
388     }
389     }
390
391     /* The extended set of charsets */
392     private static Object JavaDoc extendedProviderLock = new Object JavaDoc();
393     private static boolean extendedProviderProbed = false;
394     private static CharsetProvider JavaDoc extendedProvider = null;
395
396     private static void probeExtendedProvider() {
397     AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
398         public Object JavaDoc run() {
399             try {
400             Class JavaDoc epc
401                 = Class.forName("sun.nio.cs.ext.ExtendedCharsets");
402             extendedProvider = (CharsetProvider JavaDoc)epc.newInstance();
403             } catch (ClassNotFoundException JavaDoc x) {
404             // Extended charsets not available
405
// (charsets.jar not present)
406
} catch (InstantiationException JavaDoc x) {
407             throw new Error JavaDoc(x);
408             } catch (IllegalAccessException JavaDoc x) {
409             throw new Error JavaDoc(x);
410             }
411             return null;
412         }
413         });
414     }
415
416     private static Charset JavaDoc lookupExtendedCharset(String JavaDoc charsetName) {
417     CharsetProvider JavaDoc ecp = null;
418     synchronized (extendedProviderLock) {
419         if (!extendedProviderProbed) {
420         probeExtendedProvider();
421         extendedProviderProbed = true;
422         }
423         ecp = extendedProvider;
424     }
425     return (ecp != null) ? ecp.charsetForName(charsetName) : null;
426     }
427
428     private static Charset JavaDoc lookup(String JavaDoc charsetName) {
429     if (charsetName == null)
430         throw new IllegalArgumentException JavaDoc("Null charset name");
431
432     Object JavaDoc[] a;
433     if ((a = cache1) != null && charsetName.equals(a[0]))
434         return (Charset JavaDoc)a[1];
435     // We expect most programs to use one Charset repeatedly.
436
// We convey a hint to this effect to the VM by putting the
437
// level 1 cache miss code in a separate method.
438
return lookup2(charsetName);
439     }
440
441     private static Charset JavaDoc lookup2(String JavaDoc charsetName) {
442     Object JavaDoc[] a;
443     if ((a = cache2) != null && charsetName.equals(a[0])) {
444         cache2 = cache1;
445         cache1 = a;
446         return (Charset JavaDoc)a[1];
447     }
448
449     Charset JavaDoc cs;
450     if ((cs = standardProvider.charsetForName(charsetName)) != null ||
451         (cs = lookupExtendedCharset(charsetName)) != null ||
452         (cs = lookupViaProviders(charsetName)) != null)
453     {
454         cache(charsetName, cs);
455         return cs;
456     }
457
458     /* Only need to check the name if we didn't find a charset for it */
459     checkName(charsetName);
460     return null;
461     }
462
463     /**
464      * Tells whether the named charset is supported. </p>
465      *
466      * @param charsetName
467      * The name of the requested charset; may be either
468      * a canonical name or an alias
469      *
470      * @return <tt>true</tt> if, and only if, support for the named charset
471      * is available in the current Java virtual machine
472      *
473      * @throws IllegalCharsetNameException
474      * If the given charset name is illegal
475      */

476     public static boolean isSupported(String JavaDoc charsetName) {
477     return (lookup(charsetName) != null);
478     }
479
480     /**
481      * Returns a charset object for the named charset. </p>
482      *
483      * @param charsetName
484      * The name of the requested charset; may be either
485      * a canonical name or an alias
486      *
487      * @return A charset object for the named charset
488      *
489      * @throws IllegalCharsetNameException
490      * If the given charset name is illegal
491      *
492      * @throws UnsupportedCharsetException
493      * If no support for the named charset is available
494      * in this instance of the Java virtual machine
495      */

496     public static Charset JavaDoc forName(String JavaDoc charsetName) {
497     Charset JavaDoc cs = lookup(charsetName);
498     if (cs != null)
499         return cs;
500     throw new UnsupportedCharsetException JavaDoc(charsetName);
501     }
502
503     // Fold charsets from the given iterator into the given map, ignoring
504
// charsets whose names already have entries in the map.
505
//
506
private static void put(Iterator JavaDoc i, Map JavaDoc m) {
507     while (i.hasNext()) {
508         Charset JavaDoc cs = (Charset JavaDoc)i.next();
509         if (!m.containsKey(cs.name()))
510         m.put(cs.name(), cs);
511     }
512     }
513
514     /**
515      * Constructs a sorted map from canonical charset names to charset objects.
516      *
517      * <p> The map returned by this method will have one entry for each charset
518      * for which support is available in the current Java virtual machine. If
519      * two or more supported charsets have the same canonical name then the
520      * resulting map will contain just one of them; which one it will contain
521      * is not specified. </p>
522      *
523      * <p> The invocation of this method, and the subsequent use of the
524      * resulting map, may cause time-consuming disk or network I/O operations
525      * to occur. This method is provided for applications that need to
526      * enumerate all of the available charsets, for example to allow user
527      * charset selection. This method is not used by the {@link #forName
528      * forName} method, which instead employs an efficient incremental lookup
529      * algorithm.
530      *
531      * <p> This method may return different results at different times if new
532      * charset providers are dynamically made available to the current Java
533      * virtual machine. In the absence of such changes, the charsets returned
534      * by this method are exactly those that can be retrieved via the {@link
535      * #forName forName} method. </p>
536      *
537      * @return An immutable, case-insensitive map from canonical charset names
538      * to charset objects
539      */

540     public static SortedMap JavaDoc<String JavaDoc,Charset JavaDoc> availableCharsets() {
541     return (SortedMap JavaDoc)AccessController
542         .doPrivileged(new PrivilegedAction JavaDoc() {
543         public Object JavaDoc run() {
544             TreeMap JavaDoc m = new TreeMap JavaDoc(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER);
545             put(standardProvider.charsets(), m);
546             for (Iterator JavaDoc i = providers(); i.hasNext();) {
547             CharsetProvider JavaDoc cp = (CharsetProvider JavaDoc)i.next();
548             put(cp.charsets(), m);
549             }
550             return Collections.unmodifiableSortedMap(m);
551         }
552         });
553     }
554
555     private static Charset JavaDoc defaultCharset;
556
557     /**
558      * Returns the default charset of this Java virtual machine.
559      *
560      * <p> The default charset is determined during virtual-machine startup and
561      * typically depends upon the locale and charset of the underlying
562      * operating system.
563      *
564      * @return A charset object for the default charset
565      *
566      * @since 1.5
567      */

568     public static Charset JavaDoc defaultCharset() {
569     synchronized (Charset JavaDoc.class) {
570         if (defaultCharset == null) {
571         java.security.PrivilegedAction JavaDoc pa =
572             new GetPropertyAction("file.encoding");
573         String JavaDoc csn = (String JavaDoc)AccessController.doPrivileged(pa);
574         Charset JavaDoc cs = lookup(csn);
575         if (cs != null)
576             return cs;
577         return forName("UTF-8");
578         }
579         return defaultCharset;
580     }
581     }
582
583
584     /* -- Instance fields and methods -- */
585
586     private final String JavaDoc name; // tickles a bug in oldjavac
587
private final String JavaDoc[] aliases; // tickles a bug in oldjavac
588
private Set JavaDoc aliasSet = null;
589
590     /**
591      * Initializes a new charset with the given canonical name and alias
592      * set. </p>
593      *
594      * @param canonicalName
595      * The canonical name of this charset
596      *
597      * @param aliases
598      * An array of this charset's aliases, or null if it has no aliases
599      *
600      * @throws IllegalCharsetNameException
601      * If the canonical name or any of the aliases are illegal
602      */

603     protected Charset(String JavaDoc canonicalName, String JavaDoc[] aliases) {
604     checkName(canonicalName);
605     String JavaDoc[] as = (aliases == null) ? new String JavaDoc[0] : aliases;
606     for (int i = 0; i < as.length; i++)
607         checkName(as[i]);
608     this.name = canonicalName;
609     this.aliases = as;
610     }
611
612     /**
613      * Returns this charset's canonical name. </p>
614      *
615      * @return The canonical name of this charset
616      */

617     public final String JavaDoc name() {
618     return name;
619     }
620
621     /**
622      * Returns a set containing this charset's aliases. </p>
623      *
624      * @return An immutable set of this charset's aliases
625      */

626     public final Set JavaDoc<String JavaDoc> aliases() {
627     if (aliasSet != null)
628         return aliasSet;
629     int n = aliases.length;
630     HashSet JavaDoc hs = new HashSet JavaDoc(n);
631     for (int i = 0; i < n; i++)
632         hs.add(aliases[i]);
633     aliasSet = Collections.unmodifiableSet(hs);
634     return aliasSet;
635     }
636
637     /**
638      * Returns this charset's human-readable name for the default locale.
639      *
640      * <p> The default implementation of this method simply returns this
641      * charset's canonical name. Concrete subclasses of this class may
642      * override this method in order to provide a localized display name. </p>
643      *
644      * @return The display name of this charset in the default locale
645      */

646     public String JavaDoc displayName() {
647     return name;
648     }
649
650     /**
651      * Tells whether or not this charset is registered in the <a
652      * HREF="http://www.iana.org/assignments/character-sets">IANA Charset
653      * Registry</a>. </p>
654      *
655      * @return <tt>true</tt> if, and only if, this charset is known by its
656      * implementor to be registered with the IANA
657      */

658     public final boolean isRegistered() {
659     return !name.startsWith("X-") && !name.startsWith("x-");
660     }
661
662     /**
663      * Returns this charset's human-readable name for the given locale.
664      *
665      * <p> The default implementation of this method simply returns this
666      * charset's canonical name. Concrete subclasses of this class may
667      * override this method in order to provide a localized display name. </p>
668      *
669      * @param locale
670      * The locale for which the display name is to be retrieved
671      *
672      * @return The display name of this charset in the given locale
673      */

674     public String JavaDoc displayName(Locale JavaDoc locale) {
675     return name;
676     }
677
678     /**
679      * Tells whether or not this charset contains the given charset.
680      *
681      * <p> A charset <i>C</i> is said to <i>contain</i> a charset <i>D</i> if,
682      * and only if, every character representable in <i>D</i> is also
683      * representable in <i>C</i>. If this relationship holds then it is
684      * guaranteed that every string that can be encoded in <i>D</i> can also be
685      * encoded in <i>C</i> without performing any replacements.
686      *
687      * <p> That <i>C</i> contains <i>D</i> does not imply that each character
688      * representable in <i>C</i> by a particular byte sequence is represented
689      * in <i>D</i> by the same byte sequence, although sometimes this is the
690      * case.
691      *
692      * <p> Every charset contains itself.
693      *
694      * <p> This method computes an approximation of the containment relation:
695      * If it returns <tt>true</tt> then the given charset is known to be
696      * contained by this charset; if it returns <tt>false</tt>, however, then
697      * it is not necessarily the case that the given charset is not contained
698      * in this charset.
699      *
700      * @return <tt>true</tt> if, and only if, the given charset
701      * is contained in this charset
702      */

703     public abstract boolean contains(Charset JavaDoc cs);
704
705     /**
706      * Constructs a new decoder for this charset. </p>
707      *
708      * @return A new decoder for this charset
709      */

710     public abstract CharsetDecoder JavaDoc newDecoder();
711
712     /**
713      * Constructs a new encoder for this charset. </p>
714      *
715      * @return A new encoder for this charset
716      *
717      * @throws UnsupportedOperationException
718      * If this charset does not support encoding
719      */

720     public abstract CharsetEncoder JavaDoc newEncoder();
721
722     /**
723      * Tells whether or not this charset supports encoding.
724      *
725      * <p> Nearly all charsets support encoding. The primary exceptions are
726      * special-purpose <i>auto-detect</i> charsets whose decoders can determine
727      * which of several possible encoding schemes is in use by examining the
728      * input byte sequence. Such charsets do not support encoding because
729      * there is no way to determine which encoding should be used on output.
730      * Implementations of such charsets should override this method to return
731      * <tt>false</tt>. </p>
732      *
733      * @return <tt>true</tt> if, and only if, this charset supports encoding
734      */

735     public boolean canEncode() {
736     return true;
737     }
738
739     /**
740      * Convenience method that decodes bytes in this charset into Unicode
741      * characters.
742      *
743      * <p> An invocation of this method upon a charset <tt>cs</tt> returns the
744      * same result as the expression
745      *
746      * <pre>
747      * cs.newDecoder()
748      * .onMalformedInput(CodingErrorAction.REPLACE)
749      * .onUnmappableCharacter(CodingErrorAction.REPLACE)
750      * .decode(bb); </pre>
751      *
752      * except that it is potentially more efficient because it can cache
753      * decoders between successive invocations.
754      *
755      * <p> This method always replaces malformed-input and unmappable-character
756      * sequences with this charset's default replacement byte array. In order
757      * to detect such sequences, use the {@link
758      * CharsetDecoder#decode(java.nio.ByteBuffer)} method directly. </p>
759      *
760      * @param bb The byte buffer to be decoded
761      *
762      * @return A char buffer containing the decoded characters
763      */

764     public final CharBuffer JavaDoc decode(ByteBuffer JavaDoc bb) {
765     try {
766         return ThreadLocalCoders.decoderFor(this)
767         .onMalformedInput(CodingErrorAction.REPLACE)
768         .onUnmappableCharacter(CodingErrorAction.REPLACE)
769         .decode(bb);
770     } catch (CharacterCodingException JavaDoc x) {
771         throw new Error JavaDoc(x); // Can't happen
772
}
773     }
774
775     /**
776      * Convenience method that encodes Unicode characters into bytes in this
777      * charset.
778      *
779      * <p> An invocation of this method upon a charset <tt>cs</tt> returns the
780      * same result as the expression
781      *
782      * <pre>
783      * cs.newEncoder()
784      * .onMalformedInput(CodingErrorAction.REPLACE)
785      * .onUnmappableCharacter(CodingErrorAction.REPLACE)
786      * .encode(bb); </pre>
787      *
788      * except that it is potentially more efficient because it can cache
789      * encoders between successive invocations.
790      *
791      * <p> This method always replaces malformed-input and unmappable-character
792      * sequences with this charset's default replacement string. In order to
793      * detect such sequences, use the {@link
794      * CharsetEncoder#encode(java.nio.CharBuffer)} method directly. </p>
795      *
796      * @param cb The char buffer to be encoded
797      *
798      * @return A byte buffer containing the encoded characters
799      */

800     public final ByteBuffer JavaDoc encode(CharBuffer JavaDoc cb) {
801     try {
802         return ThreadLocalCoders.encoderFor(this)
803         .onMalformedInput(CodingErrorAction.REPLACE)
804         .onUnmappableCharacter(CodingErrorAction.REPLACE)
805         .encode(cb);
806     } catch (CharacterCodingException JavaDoc x) {
807         throw new Error JavaDoc(x); // Can't happen
808
}
809     }
810
811     /**
812      * Convenience method that encodes a string into bytes in this charset.
813      *
814      * <p> An invocation of this method upon a charset <tt>cs</tt> returns the
815      * same result as the expression
816      *
817      * <pre>
818      * cs.encode(CharBuffer.wrap(s)); </pre>
819      *
820      * @param str The string to be encoded
821      *
822      * @return A byte buffer containing the encoded characters
823      */

824     public final ByteBuffer JavaDoc encode(String JavaDoc str) {
825     return encode(CharBuffer.wrap(str));
826     }
827
828     /**
829      * Compares this charset to another.
830      *
831      * <p> Charsets are ordered by their canonical names, without regard to
832      * case. </p>
833      *
834      * @param that
835      * The charset to which this charset is to be compared
836      *
837      * @return A negative integer, zero, or a positive integer as this charset
838      * is less than, equal to, or greater than the specified charset
839      */

840     public final int compareTo(Charset JavaDoc that) {
841     return (name().compareToIgnoreCase(that.name()));
842     }
843
844     /**
845      * Computes a hashcode for this charset. </p>
846      *
847      * @return An integer hashcode
848      */

849     public final int hashCode() {
850     return name().hashCode();
851     }
852
853     /**
854      * Tells whether or not this object is equal to another.
855      *
856      * <p> Two charsets are equal if, and only if, they have the same canonical
857      * names. A charset is never equal to any other type of object. </p>
858      *
859      * @return <tt>true</tt> if, and only if, this charset is equal to the
860      * given object
861      */

862     public final boolean equals(Object JavaDoc ob) {
863     if (!(ob instanceof Charset JavaDoc))
864         return false;
865     if (this == ob)
866         return true;
867     return name.equals(((Charset JavaDoc)ob).name());
868     }
869
870     /**
871      * Returns a string describing this charset. </p>
872      *
873      * @return A string describing this charset
874      */

875     public final String JavaDoc toString() {
876     return name();
877     }
878
879 }
880
Popular Tags