View Javadoc

1   /*
2    * Copyright 2009 Red Hat, Inc.
3    *
4    * Red Hat licenses this file to you under the Apache License, version 2.0
5    * (the "License"); you may not use this file except in compliance with the
6    * License.  You may obtain a copy of the License at:
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package org.jboss.netty.util;
17  
18  import java.nio.charset.Charset;
19  import java.nio.charset.CharsetDecoder;
20  import java.nio.charset.CharsetEncoder;
21  import java.nio.charset.CodingErrorAction;
22  import java.util.IdentityHashMap;
23  import java.util.Map;
24  
25  /**
26   * A utility class that provides various common operations and constants
27   * related with {@link Charset} and its relevant classes.
28   *
29   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
30   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
31   * @version $Rev: 2080 $, $Date: 2010-01-26 18:04:19 +0900 (Tue, 26 Jan 2010) $
32   */
33  public class CharsetUtil {
34  
35      /**
36       * 16-bit UTF (UCS Transformation Format) whose byte order is identified by
37       * an optional byte-order mark
38       */
39      public static final Charset UTF_16 = Charset.forName("UTF-16");
40  
41      /**
42       * 16-bit UTF (UCS Transformation Format) whose byte order is big-endian
43       */
44      public static final Charset UTF_16BE = Charset.forName("UTF-16BE");
45  
46      /**
47       * 16-bit UTF (UCS Transformation Format) whose byte order is little-endian
48       */
49      public static final Charset UTF_16LE = Charset.forName("UTF-16LE");
50  
51      /**
52       * 8-bit UTF (UCS Transformation Format)
53       */
54      public static final Charset UTF_8 = Charset.forName("UTF-8");
55  
56      /**
57       * ISO Latin Alphabet No. 1, as known as <tt>ISO-LATIN-1</tt>
58       */
59      public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
60  
61      /**
62       * 7-bit ASCII, as known as ISO646-US or the Basic Latin block of the
63       * Unicode character set
64       */
65      public static final Charset US_ASCII = Charset.forName("US-ASCII");
66  
67      private static final ThreadLocal<Map<Charset, CharsetEncoder>> encoders =
68          new ThreadLocal<Map<Charset,CharsetEncoder>>() {
69              @Override
70              protected Map<Charset, CharsetEncoder> initialValue() {
71                  return new IdentityHashMap<Charset, CharsetEncoder>();
72              }
73          };
74  
75      private static final ThreadLocal<Map<Charset, CharsetDecoder>> decoders =
76          new ThreadLocal<Map<Charset,CharsetDecoder>>() {
77              @Override
78              protected Map<Charset, CharsetDecoder> initialValue() {
79                  return new IdentityHashMap<Charset, CharsetDecoder>();
80              }
81          };
82  
83      /**
84       * Returns a cached thread-local {@link CharsetEncoder} for the specified
85       * <tt>charset</tt>.
86       */
87      public static CharsetEncoder getEncoder(Charset charset) {
88          if (charset == null) {
89              throw new NullPointerException("charset");
90          }
91  
92          Map<Charset, CharsetEncoder> map = encoders.get();
93          CharsetEncoder e = map.get(charset);
94          if (e != null) {
95              e.reset();
96              e.onMalformedInput(CodingErrorAction.REPLACE);
97              e.onUnmappableCharacter(CodingErrorAction.REPLACE);
98              return e;
99          }
100 
101         e = charset.newEncoder();
102         e.onMalformedInput(CodingErrorAction.REPLACE);
103         e.onUnmappableCharacter(CodingErrorAction.REPLACE);
104         map.put(charset, e);
105         return e;
106     }
107 
108     /**
109      * Returns a cached thread-local {@link CharsetDecoder} for the specified
110      * <tt>charset</tt>.
111      */
112     public static CharsetDecoder getDecoder(Charset charset) {
113         if (charset == null) {
114             throw new NullPointerException("charset");
115         }
116 
117         Map<Charset, CharsetDecoder> map = decoders.get();
118         CharsetDecoder d = map.get(charset);
119         if (d != null) {
120             d.reset();
121             d.onMalformedInput(CodingErrorAction.REPLACE);
122             d.onUnmappableCharacter(CodingErrorAction.REPLACE);
123             return d;
124         }
125 
126         d = charset.newDecoder();
127         d.onMalformedInput(CodingErrorAction.REPLACE);
128         d.onUnmappableCharacter(CodingErrorAction.REPLACE);
129         map.put(charset, d);
130         return d;
131     }
132 
133     private CharsetUtil() {
134         // Unused
135     }
136 }