1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45:
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57:
58:
63: public abstract class Charset implements Comparable
64: {
65: private CharsetEncoder cachedEncoder;
66: private CharsetDecoder cachedDecoder;
67:
68:
71: private static CharsetProvider[] providers;
72:
73: private final String canonicalName;
74: private final String[] aliases;
75:
76: protected Charset (String canonicalName, String[] aliases)
77: {
78: checkName (canonicalName);
79: if (aliases != null)
80: {
81: int n = aliases.length;
82: for (int i = 0; i < n; ++i)
83: checkName (aliases[i]);
84: }
85:
86: cachedEncoder = null;
87: cachedDecoder = null;
88: this.canonicalName = canonicalName;
89: this.aliases = aliases;
90: }
91:
92:
95: private static void checkName (String name)
96: {
97: int n = name.length ();
98:
99: if (n == 0)
100: throw new IllegalCharsetNameException (name);
101:
102: char ch = name.charAt (0);
103: if (!(('A' <= ch && ch <= 'Z')
104: || ('a' <= ch && ch <= 'z')
105: || ('0' <= ch && ch <= '9')))
106: throw new IllegalCharsetNameException (name);
107:
108: for (int i = 1; i < n; ++i)
109: {
110: ch = name.charAt (i);
111: if (!(('A' <= ch && ch <= 'Z')
112: || ('a' <= ch && ch <= 'z')
113: || ('0' <= ch && ch <= '9')
114: || ch == '-' || ch == '.' || ch == ':' || ch == '_'))
115: throw new IllegalCharsetNameException (name);
116: }
117: }
118:
119:
125: public static Charset defaultCharset()
126: {
127: String encoding;
128:
129: try
130: {
131: encoding = SystemProperties.getProperty("file.encoding");
132: }
133: catch(SecurityException e)
134: {
135:
136: encoding = "ISO-8859-1";
137: }
138: catch(IllegalArgumentException e)
139: {
140:
141: encoding = "ISO-8859-1";
142: }
143:
144: try
145: {
146: return forName(encoding);
147: }
148: catch(UnsupportedCharsetException e)
149: {
150:
151: }
152: catch(IllegalCharsetNameException e)
153: {
154:
155: }
156: catch(IllegalArgumentException e)
157: {
158:
159: }
160:
161: throw new IllegalStateException("Can't get default charset!");
162: }
163:
164: public static boolean isSupported (String charsetName)
165: {
166: return charsetForName (charsetName) != null;
167: }
168:
169:
180: public static Charset forName (String charsetName)
181: {
182:
183: if(charsetName == null)
184: throw new IllegalArgumentException("Charset name must not be null.");
185:
186: Charset cs = charsetForName (charsetName);
187: if (cs == null)
188: throw new UnsupportedCharsetException (charsetName);
189: return cs;
190: }
191:
192:
200: private static Charset charsetForName(String charsetName)
201: {
202: checkName (charsetName);
203:
204:
205:
206: Charset cs = provider().charsetForName(charsetName);
207: if (cs == null)
208: {
209: CharsetProvider[] providers = providers2();
210: for (int i = 0; i < providers.length; i++)
211: {
212: cs = providers[i].charsetForName(charsetName);
213: if (cs != null)
214: break;
215: }
216: }
217: return cs;
218: }
219:
220: public static SortedMap availableCharsets()
221: {
222: TreeMap charsets = new TreeMap(String.CASE_INSENSITIVE_ORDER);
223: for (Iterator i = provider().charsets(); i.hasNext(); )
224: {
225: Charset cs = (Charset) i.next();
226: charsets.put(cs.name(), cs);
227: }
228:
229: CharsetProvider[] providers = providers2();
230: for (int j = 0; j < providers.length; j++)
231: {
232: for (Iterator i = providers[j].charsets(); i.hasNext(); )
233: {
234: Charset cs = (Charset) i.next();
235: charsets.put(cs.name(), cs);
236: }
237: }
238:
239: return Collections.unmodifiableSortedMap(charsets);
240: }
241:
242: private static CharsetProvider provider()
243: {
244: String useIconv = SystemProperties.getProperty
245: ("gnu.classpath.nio.charset.provider.iconv");
246:
247: if (useIconv != null)
248: return IconvProvider.provider();
249:
250: return Provider.provider();
251: }
252:
253:
258: private static CharsetProvider[] providers2()
259: {
260: if (providers == null)
261: {
262: try
263: {
264: Iterator i = ServiceFactory.lookupProviders(CharsetProvider.class);
265: LinkedHashSet set = new LinkedHashSet();
266: while (i.hasNext())
267: set.add(i.next());
268:
269: providers = new CharsetProvider[set.size()];
270: set.toArray(providers);
271: }
272: catch (Exception e)
273: {
274: throw new RuntimeException(e);
275: }
276: }
277: return providers;
278: }
279:
280: public final String name ()
281: {
282: return canonicalName;
283: }
284:
285: public final Set aliases ()
286: {
287: if (aliases == null)
288: return Collections.EMPTY_SET;
289:
290:
291: int n = aliases.length;
292: HashSet aliasSet = new HashSet (n);
293: for (int i = 0; i < n; ++i)
294: aliasSet.add (aliases[i]);
295: return Collections.unmodifiableSet (aliasSet);
296: }
297:
298: public String displayName ()
299: {
300: return canonicalName;
301: }
302:
303: public String displayName (Locale locale)
304: {
305: return canonicalName;
306: }
307:
308: public final boolean isRegistered ()
309: {
310: return (!canonicalName.startsWith ("x-")
311: && !canonicalName.startsWith ("X-"));
312: }
313:
314: public abstract boolean contains (Charset cs);
315:
316: public abstract CharsetDecoder newDecoder ();
317:
318: public abstract CharsetEncoder newEncoder ();
319:
320: public boolean canEncode ()
321: {
322: return true;
323: }
324:
325:
326:
327:
328:
329: public final synchronized ByteBuffer encode (CharBuffer cb)
330: {
331: try
332: {
333: if (cachedEncoder == null)
334: {
335: cachedEncoder = newEncoder ()
336: .onMalformedInput (CodingErrorAction.REPLACE)
337: .onUnmappableCharacter (CodingErrorAction.REPLACE);
338: } else
339: cachedEncoder.reset();
340: return cachedEncoder.encode (cb);
341: }
342: catch (CharacterCodingException e)
343: {
344: throw new AssertionError (e);
345: }
346: }
347:
348: public final ByteBuffer encode (String str)
349: {
350: return encode (CharBuffer.wrap (str));
351: }
352:
353:
354:
355:
356:
357: public final synchronized CharBuffer decode (ByteBuffer bb)
358: {
359: try
360: {
361: if (cachedDecoder == null)
362: {
363: cachedDecoder = newDecoder ()
364: .onMalformedInput (CodingErrorAction.REPLACE)
365: .onUnmappableCharacter (CodingErrorAction.REPLACE);
366: } else
367: cachedDecoder.reset();
368:
369: return cachedDecoder.decode (bb);
370: }
371: catch (CharacterCodingException e)
372: {
373: throw new AssertionError (e);
374: }
375: }
376:
377: public final int compareTo (Object ob)
378: {
379: return canonicalName.compareToIgnoreCase (((Charset) ob).canonicalName);
380: }
381:
382: public final int hashCode ()
383: {
384: return canonicalName.hashCode ();
385: }
386:
387: public final boolean equals (Object ob)
388: {
389: if (ob instanceof Charset)
390: return canonicalName.equalsIgnoreCase (((Charset) ob).canonicalName);
391: else
392: return false;
393: }
394:
395: public final String toString ()
396: {
397: return canonicalName;
398: }
399: }