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