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<Charset>
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<String, Charset> availableCharsets()
223: {
224: TreeMap<String, Charset> charsets
225: = new TreeMap(String.CASE_INSENSITIVE_ORDER);
226: for (Iterator<Charset> i = provider().charsets(); i.hasNext(); )
227: {
228: Charset cs = i.next();
229: charsets.put(cs.name(), cs);
230: }
231:
232: CharsetProvider[] providers = providers2();
233: for (int j = 0; j < providers.length; j++)
234: {
235: for (Iterator<Charset> i = providers[j].charsets(); i.hasNext(); )
236: {
237: Charset cs = (Charset) i.next();
238: charsets.put(cs.name(), cs);
239: }
240: }
241:
242: return Collections.unmodifiableSortedMap(charsets);
243: }
244:
245: private static CharsetProvider provider()
246: {
247: String useIconv = SystemProperties.getProperty
248: ("gnu.classpath.nio.charset.provider.iconv");
249:
250: if (useIconv != null)
251: return IconvProvider.provider();
252:
253: return Provider.provider();
254: }
255:
256:
261: private static CharsetProvider[] providers2()
262: {
263: if (providers == null)
264: {
265: try
266: {
267: Iterator i = ServiceFactory.lookupProviders(CharsetProvider.class);
268: LinkedHashSet set = new LinkedHashSet();
269: while (i.hasNext())
270: set.add(i.next());
271:
272: providers = new CharsetProvider[set.size()];
273: set.toArray(providers);
274: }
275: catch (Exception e)
276: {
277: throw new RuntimeException(e);
278: }
279: }
280: return providers;
281: }
282:
283: public final String name ()
284: {
285: return canonicalName;
286: }
287:
288: public final Set<String> aliases ()
289: {
290: if (aliases == null)
291: return Collections.<String>emptySet();
292:
293:
294: int n = aliases.length;
295: HashSet<String> aliasSet = new HashSet<String> (n);
296: for (int i = 0; i < n; ++i)
297: aliasSet.add (aliases[i]);
298: return Collections.unmodifiableSet (aliasSet);
299: }
300:
301: public String displayName ()
302: {
303: return canonicalName;
304: }
305:
306: public String displayName (Locale locale)
307: {
308: return canonicalName;
309: }
310:
311: public final boolean isRegistered ()
312: {
313: return (!canonicalName.startsWith ("x-")
314: && !canonicalName.startsWith ("X-"));
315: }
316:
317: public abstract boolean contains (Charset cs);
318:
319: public abstract CharsetDecoder newDecoder ();
320:
321: public abstract CharsetEncoder newEncoder ();
322:
323: public boolean canEncode ()
324: {
325: return true;
326: }
327:
328:
329:
330:
331:
332: public final synchronized ByteBuffer encode (CharBuffer cb)
333: {
334: try
335: {
336: if (cachedEncoder == null)
337: {
338: cachedEncoder = newEncoder ()
339: .onMalformedInput (CodingErrorAction.REPLACE)
340: .onUnmappableCharacter (CodingErrorAction.REPLACE);
341: } else
342: cachedEncoder.reset();
343: return cachedEncoder.encode (cb);
344: }
345: catch (CharacterCodingException e)
346: {
347: throw new AssertionError (e);
348: }
349: }
350:
351: public final ByteBuffer encode (String str)
352: {
353: return encode (CharBuffer.wrap (str));
354: }
355:
356:
357:
358:
359:
360: public final synchronized CharBuffer decode (ByteBuffer bb)
361: {
362: try
363: {
364: if (cachedDecoder == null)
365: {
366: cachedDecoder = newDecoder ()
367: .onMalformedInput (CodingErrorAction.REPLACE)
368: .onUnmappableCharacter (CodingErrorAction.REPLACE);
369: } else
370: cachedDecoder.reset();
371:
372: return cachedDecoder.decode (bb);
373: }
374: catch (CharacterCodingException e)
375: {
376: throw new AssertionError (e);
377: }
378: }
379:
380: public final int compareTo (Charset other)
381: {
382: return canonicalName.compareToIgnoreCase (other.canonicalName);
383: }
384:
385: public final int hashCode ()
386: {
387: return canonicalName.hashCode ();
388: }
389:
390: public final boolean equals (Object ob)
391: {
392: if (ob instanceof Charset)
393: return canonicalName.equalsIgnoreCase (((Charset) ob).canonicalName);
394: else
395: return false;
396: }
397:
398: public final String toString ()
399: {
400: return canonicalName;
401: }
402: }