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