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:
127: public static Charset defaultCharset()
128: {
129: String encoding;
130:
131: try
132: {
133: encoding = SystemProperties.getProperty("file.encoding");
134: }
135: catch(SecurityException e)
136: {
137:
138: encoding = "ISO-8859-1";
139: }
140: catch(IllegalArgumentException e)
141: {
142:
143: encoding = "ISO-8859-1";
144: }
145:
146: try
147: {
148: return forName(encoding);
149: }
150: catch(UnsupportedCharsetException e)
151: {
152:
153: }
154: catch(IllegalCharsetNameException e)
155: {
156:
157: }
158: catch(IllegalArgumentException e)
159: {
160:
161: }
162:
163: throw new IllegalStateException("Can't get default charset!");
164: }
165:
166: public static boolean isSupported (String charsetName)
167: {
168: return charsetForName (charsetName) != null;
169: }
170:
171:
182: public static Charset forName (String charsetName)
183: {
184:
185: if(charsetName == null)
186: throw new IllegalArgumentException("Charset name must not be null.");
187:
188: Charset cs = charsetForName (charsetName);
189: if (cs == null)
190: throw new UnsupportedCharsetException (charsetName);
191: return cs;
192: }
193:
194:
202: private static Charset charsetForName(String charsetName)
203: {
204: checkName (charsetName);
205:
206:
207:
208: Charset cs = provider().charsetForName(charsetName);
209: if (cs == null)
210: {
211: CharsetProvider[] providers = providers2();
212: for (int i = 0; i < providers.length; i++)
213: {
214: cs = providers[i].charsetForName(charsetName);
215: if (cs != null)
216: break;
217: }
218: }
219: return cs;
220: }
221:
222: public static SortedMap availableCharsets()
223: {
224: TreeMap charsets = new TreeMap(String.CASE_INSENSITIVE_ORDER);
225: for (Iterator i = provider().charsets(); i.hasNext(); )
226: {
227: Charset cs = (Charset) i.next();
228: charsets.put(cs.name(), cs);
229: }
230:
231: CharsetProvider[] providers = providers2();
232: for (int j = 0; j < providers.length; j++)
233: {
234: for (Iterator i = providers[j].charsets(); i.hasNext(); )
235: {
236: Charset cs = (Charset) i.next();
237: charsets.put(cs.name(), cs);
238: }
239: }
240:
241: return Collections.unmodifiableSortedMap(charsets);
242: }
243:
244: private static CharsetProvider provider()
245: {
246: String useIconv = SystemProperties.getProperty
247: ("gnu.classpath.nio.charset.provider.iconv");
248:
249: if (useIconv != null)
250: return IconvProvider.provider();
251:
252: return Provider.provider();
253: }
254:
255:
260: private static CharsetProvider[] providers2()
261: {
262: if (providers == null)
263: {
264: try
265: {
266: Iterator i = ServiceFactory.lookupProviders(CharsetProvider.class);
267: LinkedHashSet set = new LinkedHashSet();
268: while (i.hasNext())
269: set.add(i.next());
270:
271: providers = new CharsetProvider[set.size()];
272: set.toArray(providers);
273: }
274: catch (Exception e)
275: {
276: throw new RuntimeException(e);
277: }
278: }
279: return providers;
280: }
281:
282: public final String name ()
283: {
284: return canonicalName;
285: }
286:
287: public final Set aliases ()
288: {
289: if (aliases == null)
290: return Collections.EMPTY_SET;
291:
292:
293: int n = aliases.length;
294: HashSet aliasSet = new HashSet (n);
295: for (int i = 0; i < n; ++i)
296: aliasSet.add (aliases[i]);
297: return Collections.unmodifiableSet (aliasSet);
298: }
299:
300: public String displayName ()
301: {
302: return canonicalName;
303: }
304:
305: public String displayName (Locale locale)
306: {
307: return canonicalName;
308: }
309:
310: public final boolean isRegistered ()
311: {
312: return (!canonicalName.startsWith ("x-")
313: && !canonicalName.startsWith ("X-"));
314: }
315:
316: public abstract boolean contains (Charset cs);
317:
318: public abstract CharsetDecoder newDecoder ();
319:
320: public abstract CharsetEncoder newEncoder ();
321:
322: public boolean canEncode ()
323: {
324: return true;
325: }
326:
327:
328:
329:
330:
331: public final synchronized ByteBuffer encode (CharBuffer cb)
332: {
333: try
334: {
335: if (cachedEncoder == null)
336: {
337: cachedEncoder = newEncoder ()
338: .onMalformedInput (CodingErrorAction.REPLACE)
339: .onUnmappableCharacter (CodingErrorAction.REPLACE);
340: } else
341: cachedEncoder.reset();
342: return cachedEncoder.encode (cb);
343: }
344: catch (CharacterCodingException e)
345: {
346: throw new AssertionError (e);
347: }
348: }
349:
350: public final ByteBuffer encode (String str)
351: {
352: return encode (CharBuffer.wrap (str));
353: }
354:
355:
356:
357:
358:
359: public final synchronized CharBuffer decode (ByteBuffer bb)
360: {
361: try
362: {
363: if (cachedDecoder == null)
364: {
365: cachedDecoder = newDecoder ()
366: .onMalformedInput (CodingErrorAction.REPLACE)
367: .onUnmappableCharacter (CodingErrorAction.REPLACE);
368: } else
369: cachedDecoder.reset();
370:
371: return cachedDecoder.decode (bb);
372: }
373: catch (CharacterCodingException e)
374: {
375: throw new AssertionError (e);
376: }
377: }
378:
379: public final int compareTo (Object ob)
380: {
381: return canonicalName.compareToIgnoreCase (((Charset) ob).canonicalName);
382: }
383:
384: public final int hashCode ()
385: {
386: return canonicalName.hashCode ();
387: }
388:
389: public final boolean equals (Object ob)
390: {
391: if (ob instanceof Charset)
392: return canonicalName.equalsIgnoreCase (((Charset) ob).canonicalName);
393: else
394: return false;
395: }
396:
397: public final String toString ()
398: {
399: return canonicalName;
400: }
401: }