1 |
/* EncodingManager.java -- Manages character encoding translators |
/* EncodingManager.java -- Manages character encoding translators |
2 |
Copyright (C) 1998, 1999 Free Software Foundation, Inc. |
Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
42 |
import java.io.InputStream; |
import java.io.InputStream; |
43 |
import java.io.OutputStream; |
import java.io.OutputStream; |
44 |
import java.io.UnsupportedEncodingException; |
import java.io.UnsupportedEncodingException; |
45 |
|
import java.security.AccessController; |
46 |
import java.util.Hashtable; |
import java.util.Hashtable; |
47 |
import java.util.StringTokenizer; |
import java.util.StringTokenizer; |
48 |
import gnu.java.io.decode.Decoder; |
import gnu.java.io.decode.Decoder; |
49 |
import gnu.java.io.encode.Encoder; |
import gnu.java.io.encode.Encoder; |
50 |
|
import gnu.java.security.action.GetPropertyAction; |
|
|
|
|
import java.io.FileOutputStream; |
|
51 |
|
|
52 |
/** |
/** |
53 |
* This class is used to create new instances of Decoders for a specified |
* This class is used to create new instances of Decoders for a specified |
100 |
private static Encoder default_encoder_instance; |
private static Encoder default_encoder_instance; |
101 |
|
|
102 |
/** |
/** |
|
* This is our hash table of previously loaded <code>Decoder</code> classes |
|
|
*/ |
|
|
private static Hashtable decoder_cons; |
|
|
|
|
|
/** |
|
103 |
* This is hash table of cached instances of <code>Decoder</code> objects |
* This is hash table of cached instances of <code>Decoder</code> objects |
104 |
*/ |
*/ |
105 |
private static Hashtable decoder_instances; |
private static Hashtable decoder_instances; |
106 |
|
|
107 |
/** |
/** |
|
* This is our hash table of previously loaded <code>Encoder</code> classes |
|
|
*/ |
|
|
private static Hashtable encoder_cons; |
|
|
|
|
|
/** |
|
108 |
* This is hash table of cached instances of <code>Encoder</code> objects |
* This is hash table of cached instances of <code>Encoder</code> objects |
109 |
*/ |
*/ |
110 |
private static Hashtable encoder_instances; |
private static Hashtable encoder_instances; |
111 |
|
|
112 |
|
/** |
113 |
|
* Helper method to get system properties in the proper security context. |
114 |
|
*/ |
115 |
|
private static String getSystemProperty(String propName, String defaultValue) |
116 |
|
{ |
117 |
|
GetPropertyAction getProp = new GetPropertyAction(propName, defaultValue); |
118 |
|
return (String)AccessController.doPrivileged(getProp); |
119 |
|
} |
120 |
|
|
121 |
static |
static |
122 |
{ |
{ |
123 |
// Initialize hashtables |
// Initialize hashtables |
|
decoder_cons = new Hashtable(); |
|
|
encoder_cons = new Hashtable(); |
|
124 |
decoder_instances = new Hashtable(); |
decoder_instances = new Hashtable(); |
125 |
encoder_instances = new Hashtable(); |
encoder_instances = new Hashtable(); |
126 |
|
|
127 |
// Find the system default decoder search path |
// Find the system default decoder search path |
128 |
encoding_path = System.getProperty("file.encoding.pkg"); |
encoding_path = getSystemProperty("file.encoding.pkg", null); |
129 |
if (encoding_path == null) |
if (encoding_path == null) |
130 |
encoding_path = "gnu.java.io"; |
encoding_path = "gnu.java.io"; |
131 |
else |
else |
132 |
encoding_path = encoding_path + ":gnu.java.io"; |
encoding_path = encoding_path + ":gnu.java.io"; |
133 |
|
|
134 |
// Find the system default encoding name |
// Find the system default encoding name |
135 |
String default_encoding = System.getProperty("file.encoding","8859_1"); |
String default_encoding = getSystemProperty("file.encoding", "8859_1"); |
136 |
|
|
137 |
// Load the class |
// Load the class |
138 |
try |
try |
139 |
{ |
{ |
140 |
// First the Decoder side |
// First the Decoder side |
141 |
default_decoder_cons = findDecoderConstructor(default_encoding, true); |
default_decoder_cons = findDecoderConstructor(default_encoding); |
142 |
|
|
143 |
Object[] objs = new Object[1]; |
Object[] objs = new Object[] { null }; |
|
objs[0] = null; |
|
144 |
|
|
145 |
default_decoder_instance = |
default_decoder_instance = |
146 |
(Decoder)default_decoder_cons.newInstance(objs); |
(Decoder)default_decoder_cons.newInstance(objs); |
147 |
|
|
148 |
// Now the Encoder side |
// Now the Encoder side |
149 |
default_encoder_cons = findEncoderConstructor(default_encoding, true); |
default_encoder_cons = findEncoderConstructor(default_encoding); |
|
|
|
|
objs = new Object[1]; |
|
|
objs[0] = null; |
|
150 |
|
|
151 |
default_encoder_instance = |
default_encoder_instance = |
152 |
(Encoder)default_encoder_cons.newInstance(objs); |
(Encoder)default_encoder_cons.newInstance(objs); |
153 |
|
|
154 |
// Add items to the hashtable; |
// Add items to the hashtable; |
|
decoder_cons.put(default_encoding, default_decoder_cons); |
|
|
encoder_cons.put(default_encoding, default_encoder_cons); |
|
155 |
decoder_instances.put(default_encoding, default_decoder_instance); |
decoder_instances.put(default_encoding, default_decoder_instance); |
156 |
encoder_instances.put(default_encoding, default_encoder_instance); |
encoder_instances.put(default_encoding, default_encoder_instance); |
157 |
} |
} |
158 |
catch(Exception e) |
catch(Exception e) |
159 |
{ |
{ |
160 |
throw new Error("Cannot load system default encoding '" + |
throw new Error("Cannot load system default encoding: " + |
161 |
default_encoding + "': " + e.getMessage()); |
default_encoding, e); |
162 |
} |
} |
163 |
} |
} |
164 |
|
|
174 |
* |
* |
175 |
* @exception UnsupportedEncodingException If a <code>Decoder</code> for this encoding cannot be found. |
* @exception UnsupportedEncodingException If a <code>Decoder</code> for this encoding cannot be found. |
176 |
*/ |
*/ |
177 |
private static Constructor |
private static Constructor findDecoderConstructor(String encoding) |
178 |
findDecoderConstructor(String encoding, boolean cache) |
throws UnsupportedEncodingException |
|
throws UnsupportedEncodingException |
|
179 |
{ |
{ |
180 |
// First check for an aliased encoding name |
// First check for an aliased encoding name |
181 |
String alias = System.getProperty("gnu.java.io.encoding_scheme_alias." + |
encoding = getSystemProperty("gnu.java.io.encoding_scheme_alias." + |
182 |
encoding); |
encoding, encoding); |
|
if (alias != null) |
|
|
encoding = alias; |
|
183 |
|
|
184 |
StringTokenizer st = new StringTokenizer(encoding_path, ":"); |
StringTokenizer st = new StringTokenizer(encoding_path, ":"); |
185 |
|
|
189 |
try |
try |
190 |
{ |
{ |
191 |
Class cls = Class.forName(classname); |
Class cls = Class.forName(classname); |
192 |
|
return cls.getConstructor(new Class[] { InputStream.class }); |
|
Class[] params = new Class[1]; |
|
|
params[0] = InputStream.class; |
|
|
|
|
|
Constructor cons = cls.getConstructor(params); |
|
|
|
|
|
if (cache) |
|
|
decoder_cons.put(encoding, cons); |
|
|
|
|
|
return(cons); |
|
193 |
} |
} |
194 |
catch(Exception e) { ; } |
catch(Exception e) { ; } |
195 |
} |
} |
205 |
* |
* |
206 |
* @exception UnsupportedEncodingException If a <code>Encoder</code> for this encoding cannot be found. |
* @exception UnsupportedEncodingException If a <code>Encoder</code> for this encoding cannot be found. |
207 |
*/ |
*/ |
208 |
private static Constructor |
private static Constructor findEncoderConstructor(String encoding) |
209 |
findEncoderConstructor(String encoding, boolean cache) |
throws UnsupportedEncodingException |
|
throws UnsupportedEncodingException |
|
210 |
{ |
{ |
211 |
// First check for an aliased encoding name |
// First check for an aliased encoding name |
212 |
String alias = System.getProperty("gnu.java.io.encoding_scheme_alias." + |
encoding = getSystemProperty("gnu.java.io.encoding_scheme_alias." + |
213 |
encoding); |
encoding, encoding); |
|
if (alias != null) |
|
|
encoding = alias; |
|
214 |
|
|
215 |
StringTokenizer st = new StringTokenizer(encoding_path, ":"); |
StringTokenizer st = new StringTokenizer(encoding_path, ":"); |
216 |
|
|
220 |
try |
try |
221 |
{ |
{ |
222 |
Class cls = Class.forName(classname); |
Class cls = Class.forName(classname); |
223 |
|
return cls.getConstructor(new Class[] { OutputStream.class }); |
|
Class[] params = new Class[1]; |
|
|
params[0] = OutputStream.class; |
|
|
|
|
|
Constructor cons = cls.getConstructor(params); |
|
|
|
|
|
if (cache) |
|
|
encoder_cons.put(encoding, cons); |
|
|
|
|
|
return(cons); |
|
224 |
} |
} |
225 |
catch(Exception e) { ; } |
catch(Exception e) { ; } |
226 |
} |
} |
238 |
* |
* |
239 |
* @return An instance of the default <code>Decoder</code>. |
* @return An instance of the default <code>Decoder</code>. |
240 |
*/ |
*/ |
241 |
public static Decoder |
public static Decoder getDecoder() |
|
getDecoder() |
|
242 |
{ |
{ |
243 |
return(default_decoder_instance); |
return default_decoder_instance; |
244 |
} |
} |
245 |
|
|
246 |
/*************************************************************************/ |
/*************************************************************************/ |
263 |
* |
* |
264 |
* @exception UnsupportedEncodingException If a <code>Decoder</code> for the named encoding cannot be found |
* @exception UnsupportedEncodingException If a <code>Decoder</code> for the named encoding cannot be found |
265 |
*/ |
*/ |
266 |
public static Decoder |
public static Decoder getDecoder(String encoding) |
267 |
getDecoder(String encoding) throws UnsupportedEncodingException |
throws UnsupportedEncodingException |
|
{ |
|
|
return(getDecoder(encoding, true)); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This method returns the default instance of the <code>Decoder</code> |
|
|
* for the named encoding. This must be used only for calling the static |
|
|
* byte array conversion methods. Calling any instance methods on this |
|
|
* object will result in a <code>NullPointerException</code> |
|
|
* |
|
|
* @param encoding The name of the encoding to retrieve a <code>Decoder</code> for. |
|
|
* @param cache <code>true</code> to cache this encoding, <code>false</code> otherwise |
|
|
* |
|
|
* @return An instance of the <code>Decoder</code> for the named encoding. |
|
|
* |
|
|
* @exception UnsupportedEncodingException If a <code>Decoder</code> for the named encoding cannot be found |
|
|
*/ |
|
|
public static Decoder |
|
|
getDecoder(String encoding, boolean cache) throws UnsupportedEncodingException |
|
268 |
{ |
{ |
269 |
Decoder dec = (Decoder)decoder_instances.get(encoding); |
Decoder dec = (Decoder)decoder_instances.get(encoding); |
270 |
if (dec != null) |
if (dec != null) |
271 |
return(dec); |
return dec; |
272 |
|
|
273 |
dec = getDecoder(null, encoding, cache); |
dec = getDecoder(null, encoding); |
274 |
|
decoder_instances.put(encoding, dec); |
275 |
if (cache) |
return dec; |
|
decoder_instances.put(encoding, dec); |
|
|
|
|
|
return(dec); |
|
276 |
} |
} |
277 |
|
|
278 |
/*************************************************************************/ |
/*************************************************************************/ |
284 |
* |
* |
285 |
* @param in The <code>InputStream</code> to read from |
* @param in The <code>InputStream</code> to read from |
286 |
*/ |
*/ |
287 |
public static Decoder |
public static Decoder getDecoder(InputStream in) |
|
getDecoder(InputStream in) |
|
288 |
{ |
{ |
|
Object[] params = new Object[1]; |
|
|
params[0] = in; |
|
|
|
|
|
Decoder dec = null; |
|
289 |
try |
try |
290 |
{ |
{ |
291 |
dec = (Decoder)default_decoder_cons.newInstance(params); |
Object[] params = new Object[] { in }; |
292 |
|
return (Decoder)default_decoder_cons.newInstance(params); |
293 |
} |
} |
294 |
catch(Exception e) |
catch(Exception e) |
295 |
{ |
{ |
296 |
throw new Error("Unexpected problems with default decoder"); |
throw new Error("Unexpected problems with default decoder", e); |
297 |
} |
} |
|
|
|
|
return(dec); |
|
298 |
} |
} |
299 |
|
|
300 |
/*************************************************************************/ |
/*************************************************************************/ |
314 |
* |
* |
315 |
* @exception UnsupportedEncodingException If a <code>Decoder</code> for this encoding cannot be found |
* @exception UnsupportedEncodingException If a <code>Decoder</code> for this encoding cannot be found |
316 |
*/ |
*/ |
317 |
public static Decoder |
public static Decoder getDecoder(InputStream in, String encoding) |
318 |
getDecoder(InputStream in, String encoding) throws UnsupportedEncodingException |
throws UnsupportedEncodingException |
319 |
{ |
{ |
320 |
return(getDecoder(in, encoding, true)); |
Constructor cons = findDecoderConstructor(encoding); |
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This method returns a <code>Decoder</code> object that can read from |
|
|
* the specified <code>InputStream</code> using the named encoding |
|
|
* |
|
|
* @param in The <code>InputStream</code> to read from |
|
|
* @param encoding The name of the character encoding scheme to use |
|
|
* @param cache <code>true</code> to cache the returned <code>Decoder</code>, <code>false</code> otherwise. |
|
|
* |
|
|
* @exception UnsupportedEncodingException If a <code>Decoder</code> for this encoding cannot be found |
|
|
*/ |
|
|
public static Decoder |
|
|
getDecoder(InputStream in, String encoding, boolean cache) |
|
|
throws UnsupportedEncodingException |
|
|
{ |
|
|
Constructor cons = findDecoderConstructor(encoding, cache); |
|
|
Object[] params = new Object[1]; |
|
|
params[0] = in; |
|
321 |
|
|
|
Decoder dec = null; |
|
322 |
try |
try |
323 |
{ |
{ |
324 |
dec = (Decoder)cons.newInstance(params); |
return (Decoder)cons.newInstance(new Object[] { in }); |
325 |
} |
} |
326 |
catch(Exception e) |
catch(Exception e) |
327 |
{ |
{ |
328 |
throw new UnsupportedEncodingException(encoding + ": " + e.getMessage()); |
throw (UnsupportedEncodingException) |
329 |
|
new UnsupportedEncodingException(encoding).initCause(e); |
330 |
} |
} |
|
|
|
|
return(dec); |
|
331 |
} |
} |
332 |
|
|
333 |
/*************************************************************************/ |
/*************************************************************************/ |
340 |
* |
* |
341 |
* @return An instance of the default <code>Encoder</code>. |
* @return An instance of the default <code>Encoder</code>. |
342 |
*/ |
*/ |
343 |
public static Encoder |
public static Encoder getEncoder() |
|
getEncoder() |
|
344 |
{ |
{ |
345 |
return(default_encoder_instance); |
return default_encoder_instance; |
346 |
} |
} |
347 |
|
|
348 |
/*************************************************************************/ |
/*************************************************************************/ |
365 |
* |
* |
366 |
* @exception UnsupportedEncodingException If a <code>Encoder</code> for the named encoding cannot be found |
* @exception UnsupportedEncodingException If a <code>Encoder</code> for the named encoding cannot be found |
367 |
*/ |
*/ |
368 |
public static Encoder |
public static Encoder getEncoder(String encoding) |
369 |
getEncoder(String encoding) throws UnsupportedEncodingException |
throws UnsupportedEncodingException |
|
{ |
|
|
return(getEncoder(encoding, true)); |
|
|
} |
|
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This method returns the default instance of the <code>Encoder</code> |
|
|
* for the named encoding. This must be used only for calling the static |
|
|
* byte array conversion methods. Calling any instance methods on this |
|
|
* object will result in a <code>NullPointerException</code> |
|
|
* |
|
|
* @param encoding The name of the encoding to retrieve a <code>Encoder</code> for. |
|
|
* @param cache <code>true</code> to cache this encoding, <code>false</code> otherwise |
|
|
* |
|
|
* @return An instance of the <code>Encoder</code> for the named encoding. |
|
|
* |
|
|
* @exception UnsupportedEncodingException If a <code>Encoder</code> for the named encoding cannot be found |
|
|
*/ |
|
|
public static Encoder |
|
|
getEncoder(String encoding, boolean cache) throws UnsupportedEncodingException |
|
370 |
{ |
{ |
371 |
Encoder enc = (Encoder)encoder_instances.get(encoding); |
Encoder enc = (Encoder)encoder_instances.get(encoding); |
372 |
if (enc != null) |
if (enc != null) |
373 |
return(enc); |
return enc; |
374 |
|
|
375 |
enc = getEncoder(null, encoding, cache); |
enc = getEncoder(null, encoding); |
376 |
|
encoder_instances.put(encoding, enc); |
377 |
if (cache) |
return enc; |
|
encoder_instances.put(encoding, enc); |
|
|
|
|
|
return(enc); |
|
378 |
} |
} |
379 |
|
|
380 |
/*************************************************************************/ |
/*************************************************************************/ |
386 |
* |
* |
387 |
* @param out The <code>OutputStream</code> to read from |
* @param out The <code>OutputStream</code> to read from |
388 |
*/ |
*/ |
389 |
public static Encoder |
public static Encoder getEncoder(OutputStream out) |
|
getEncoder(OutputStream out) |
|
390 |
{ |
{ |
|
Object[] params = new Object[1]; |
|
|
params[0] = out; |
|
|
|
|
|
Encoder enc = null; |
|
391 |
try |
try |
392 |
{ |
{ |
393 |
enc = (Encoder)default_encoder_cons.newInstance(params); |
Object[] params = new Object[] { out }; |
394 |
|
return (Encoder)default_encoder_cons.newInstance(params); |
395 |
} |
} |
396 |
catch(Exception e) |
catch(Exception e) |
397 |
{ |
{ |
398 |
throw new Error("Unexpected problems with default decoder"); |
throw new Error("Unexpected problems with default decoder", e); |
399 |
} |
} |
|
|
|
|
return(enc); |
|
400 |
} |
} |
401 |
|
|
402 |
/*************************************************************************/ |
/*************************************************************************/ |
416 |
* |
* |
417 |
* @exception UnsupportedEncodingException If an <code>Encoder</code> for this encoding cannot be found |
* @exception UnsupportedEncodingException If an <code>Encoder</code> for this encoding cannot be found |
418 |
*/ |
*/ |
419 |
public static Encoder |
public static Encoder getEncoder(OutputStream out, String encoding) |
420 |
getEncoder(OutputStream in, String encoding) throws UnsupportedEncodingException |
throws UnsupportedEncodingException |
421 |
{ |
{ |
422 |
return(getEncoder(in, encoding, true)); |
Constructor cons = findEncoderConstructor(encoding); |
|
} |
|
423 |
|
|
|
/*************************************************************************/ |
|
|
|
|
|
/** |
|
|
* This method returns an <code>Encoder</code> object that can write to |
|
|
* the specified <code>OutputStream</code> using the named encoding |
|
|
* |
|
|
* @param in The <code>OutputStream</code> to read from |
|
|
* @param encoding The name of the character encoding scheme to use |
|
|
* @param cache <code>true</code> to cache the returned <code>Encoder</code>, <code>false</code> otherwise. |
|
|
* |
|
|
* @exception UnsupportedEncodingException If a <code>Decoder</code> for this encoding cannot be found |
|
|
*/ |
|
|
public static Encoder |
|
|
getEncoder(OutputStream out, String encoding, boolean cache) |
|
|
throws UnsupportedEncodingException |
|
|
{ |
|
|
Constructor cons = findEncoderConstructor(encoding, cache); |
|
|
Object[] params = new Object[1]; |
|
|
params[0] = out; |
|
|
|
|
|
Encoder enc = null; |
|
424 |
try |
try |
425 |
{ |
{ |
426 |
enc = (Encoder)cons.newInstance(params); |
return (Encoder)cons.newInstance(new Object[] { out }); |
427 |
} |
} |
428 |
catch(Exception e) |
catch(Exception e) |
429 |
{ |
{ |
430 |
throw new UnsupportedEncodingException(encoding + ": " + e.getMessage()); |
throw (UnsupportedEncodingException) |
431 |
|
new UnsupportedEncodingException(encoding).initCause(e); |
432 |
} |
} |
|
|
|
|
return(enc); |
|
433 |
} |
} |
434 |
|
|
435 |
} // class EncodingManager |
} // class EncodingManager |
|
|
|