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