KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xml > serialize > EncodingInfo


1 /*
2  * Copyright 2000-2002,2004,2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xml.serialize;
18
19 import java.io.OutputStream JavaDoc;
20 import java.io.OutputStreamWriter JavaDoc;
21 import java.io.UnsupportedEncodingException JavaDoc;
22 import java.io.Writer JavaDoc;
23 import org.apache.xerces.util.EncodingMap;
24
25 /**
26  * This class represents an encoding.
27  *
28  * @version $Id: EncodingInfo.java,v 1.7 2005/05/22 19:11:07 mrglavas Exp $
29  */

30 public class EncodingInfo {
31     
32     // An array to hold the argument for a method of Charset, CharsetEncoder or CharToByteConverter.
33
private Object JavaDoc [] fArgsForMethod = null;
34     
35     // name of encoding as registered with IANA;
36
// preferably a MIME name, but aliases are fine too.
37
String JavaDoc ianaName;
38     String JavaDoc javaName;
39     int lastPrintable;
40     
41     // The CharsetEncoder with which we test unusual characters.
42
Object JavaDoc fCharsetEncoder = null;
43     
44     // The CharToByteConverter with which we test unusual characters.
45
Object JavaDoc fCharToByteConverter = null;
46     
47     // Is the converter null because it can't be instantiated
48
// for some reason (perhaps we're running with insufficient authority as
49
// an applet?
50
boolean fHaveTriedCToB = false;
51     
52     // Is the charset encoder usable or available.
53
boolean fHaveTriedCharsetEncoder = false;
54
55     /**
56      * Creates new <code>EncodingInfo</code> instance.
57      */

58     public EncodingInfo(String JavaDoc ianaName, String JavaDoc javaName, int lastPrintable) {
59         this.ianaName = ianaName;
60         this.javaName = EncodingMap.getIANA2JavaMapping(ianaName);
61         this.lastPrintable = lastPrintable;
62     }
63
64     /**
65      * Returns a MIME charset name of this encoding.
66      */

67     public String JavaDoc getIANAName() {
68         return this.ianaName;
69     }
70
71     /**
72      * Returns a writer for this encoding based on
73      * an output stream.
74      *
75      * @return A suitable writer
76      * @exception UnsupportedEncodingException There is no convertor
77      * to support this encoding
78      */

79     public Writer JavaDoc getWriter(OutputStream JavaDoc output)
80         throws UnsupportedEncodingException JavaDoc {
81         // this should always be true!
82
if (javaName != null)
83             return new OutputStreamWriter JavaDoc(output, javaName);
84         javaName = EncodingMap.getIANA2JavaMapping(ianaName);
85         if(javaName == null)
86             // use UTF-8 as preferred encoding
87
return new OutputStreamWriter JavaDoc(output, "UTF8");
88         return new OutputStreamWriter JavaDoc(output, javaName);
89     }
90     
91     /**
92      * Checks whether the specified character is printable or not in this encoding.
93      *
94      * @param ch a code point (0-0x10ffff)
95      */

96     public boolean isPrintable(char ch) {
97         if (ch <= this.lastPrintable) {
98             return true;
99         }
100         return isPrintable0(ch);
101     }
102     
103     /**
104      * Checks whether the specified character is printable or not in this encoding.
105      * This method accomplishes this using a java.nio.CharsetEncoder. If NIO isn't
106      * available it will attempt use a sun.io.CharToByteConverter.
107      *
108      * @param ch a code point (0-0x10ffff)
109      */

110     private boolean isPrintable0(char ch) {
111         
112         // Attempt to get a CharsetEncoder for this encoding.
113
if (fCharsetEncoder == null && CharsetMethods.fgNIOCharsetAvailable && !fHaveTriedCharsetEncoder) {
114             if (fArgsForMethod == null) {
115                 fArgsForMethod = new Object JavaDoc [1];
116             }
117             // try and create the CharsetEncoder
118
try {
119                 fArgsForMethod[0] = javaName;
120                 Object JavaDoc charset = CharsetMethods.fgCharsetForNameMethod.invoke(null, fArgsForMethod);
121                 if (((Boolean JavaDoc) CharsetMethods.fgCharsetCanEncodeMethod.invoke(charset, (Object JavaDoc[]) null)).booleanValue()) {
122                     fCharsetEncoder = CharsetMethods.fgCharsetNewEncoderMethod.invoke(charset, (Object JavaDoc[]) null);
123                 }
124                 // This charset cannot be used for encoding, don't try it again...
125
else {
126                     fHaveTriedCharsetEncoder = true;
127                 }
128             }
129             catch (Exception JavaDoc e) {
130                 // don't try it again...
131
fHaveTriedCharsetEncoder = true;
132             }
133         }
134         // Attempt to use the CharsetEncoder to determine whether the character is printable.
135
if (fCharsetEncoder != null) {
136             try {
137                 fArgsForMethod[0] = new Character JavaDoc(ch);
138                 return ((Boolean JavaDoc) CharsetMethods.fgCharsetEncoderCanEncodeMethod.invoke(fCharsetEncoder, fArgsForMethod)).booleanValue();
139             }
140             catch (Exception JavaDoc e) {
141                 // obviously can't use this charset encoder; possibly a JDK bug
142
fCharsetEncoder = null;
143                 fHaveTriedCharsetEncoder = false;
144             }
145         }
146         
147         // As a last resort try to use a sun.io.CharToByteConverter to
148
// determine whether this character is printable. We will always
149
// reach here on JDK 1.3 or below.
150
if (fCharToByteConverter == null) {
151             if (fHaveTriedCToB || !CharToByteConverterMethods.fgConvertersAvailable) {
152                 // forget it; nothing we can do...
153
return false;
154             }
155             if (fArgsForMethod == null) {
156                 fArgsForMethod = new Object JavaDoc [1];
157             }
158             // try and create the CharToByteConverter
159
try {
160                 fArgsForMethod[0] = javaName;
161                 fCharToByteConverter = CharToByteConverterMethods.fgGetConverterMethod.invoke(null, fArgsForMethod);
162             }
163             catch (Exception JavaDoc e) {
164                 // don't try it again...
165
fHaveTriedCToB = true;
166                 return false;
167             }
168         }
169         try {
170             fArgsForMethod[0] = new Character JavaDoc(ch);
171             return ((Boolean JavaDoc) CharToByteConverterMethods.fgCanConvertMethod.invoke(fCharToByteConverter, fArgsForMethod)).booleanValue();
172         }
173         catch (Exception JavaDoc e) {
174             // obviously can't use this converter; probably some kind of
175
// security restriction
176
fCharToByteConverter = null;
177             fHaveTriedCToB = false;
178             return false;
179         }
180     }
181
182     // is this an encoding name recognized by this JDK?
183
// if not, will throw UnsupportedEncodingException
184
public static void testJavaEncodingName(String JavaDoc name) throws UnsupportedEncodingException JavaDoc {
185         final byte [] bTest = {(byte)'v', (byte)'a', (byte)'l', (byte)'i', (byte)'d'};
186         String JavaDoc s = new String JavaDoc(bTest, name);
187     }
188     
189     /**
190      * Holder of methods from java.nio.charset.Charset and java.nio.charset.CharsetEncoder.
191      */

192     static class CharsetMethods {
193         
194         // Method: java.nio.charset.Charset.forName(java.lang.String)
195
private static java.lang.reflect.Method JavaDoc fgCharsetForNameMethod = null;
196         
197         // Method: java.nio.charset.Charset.canEncode()
198
private static java.lang.reflect.Method JavaDoc fgCharsetCanEncodeMethod = null;
199         
200         // Method: java.nio.charset.Charset.newEncoder()
201
private static java.lang.reflect.Method JavaDoc fgCharsetNewEncoderMethod = null;
202         
203         // Method: java.nio.charset.CharsetEncoder.canEncode(char)
204
private static java.lang.reflect.Method JavaDoc fgCharsetEncoderCanEncodeMethod = null;
205         
206         // Flag indicating whether or not java.nio.charset.* is available.
207
private static boolean fgNIOCharsetAvailable = false;
208         
209         private CharsetMethods() {}
210         
211         // Attempt to get methods for Charset and CharsetEncoder on class initialization.
212
static {
213             try {
214                 Class JavaDoc charsetClass = Class.forName("java.nio.charset.Charset");
215                 Class JavaDoc charsetEncoderClass = Class.forName("java.nio.charset.CharsetEncoder");
216                 fgCharsetForNameMethod = charsetClass.getMethod("forName", new Class JavaDoc [] {String JavaDoc.class});
217                 fgCharsetCanEncodeMethod = charsetClass.getMethod("canEncode", new Class JavaDoc [] {});
218                 fgCharsetNewEncoderMethod = charsetClass.getMethod("newEncoder", new Class JavaDoc [] {});
219                 fgCharsetEncoderCanEncodeMethod = charsetEncoderClass.getMethod("canEncode", new Class JavaDoc [] {Character.TYPE});
220                 fgNIOCharsetAvailable = true;
221             }
222             // ClassNotFoundException, NoSuchMethodException or SecurityException
223
// Whatever the case, we cannot use java.nio.charset.*.
224
catch (Exception JavaDoc exc) {
225                 fgCharsetForNameMethod = null;
226                 fgCharsetCanEncodeMethod = null;
227                 fgCharsetEncoderCanEncodeMethod = null;
228                 fgCharsetNewEncoderMethod = null;
229                 fgNIOCharsetAvailable = false;
230             }
231         }
232     }
233     
234     /**
235      * Holder of methods from sun.io.CharToByteConverter.
236      */

237     static class CharToByteConverterMethods {
238         
239         // Method: sun.io.CharToByteConverter.getConverter(java.lang.String)
240
private static java.lang.reflect.Method JavaDoc fgGetConverterMethod = null;
241         
242         // Method: sun.io.CharToByteConverter.canConvert(char)
243
private static java.lang.reflect.Method JavaDoc fgCanConvertMethod = null;
244         
245         // Flag indicating whether or not sun.io.CharToByteConverter is available.
246
private static boolean fgConvertersAvailable = false;
247         
248         private CharToByteConverterMethods() {}
249         
250         // Attempt to get methods for char to byte converter on class initialization.
251
static {
252             try {
253                 Class JavaDoc clazz = Class.forName("sun.io.CharToByteConverter");
254                 fgGetConverterMethod = clazz.getMethod("getConverter", new Class JavaDoc [] {String JavaDoc.class});
255                 fgCanConvertMethod = clazz.getMethod("canConvert", new Class JavaDoc [] {Character.TYPE});
256                 fgConvertersAvailable = true;
257             }
258             // ClassNotFoundException, NoSuchMethodException or SecurityException
259
// Whatever the case, we cannot use sun.io.CharToByteConverter.
260
catch (Exception JavaDoc exc) {
261                 fgGetConverterMethod = null;
262                 fgCanConvertMethod = null;
263                 fgConvertersAvailable = false;
264             }
265         }
266     }
267 }
268
Popular Tags