jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serialize/EncodingInfo.java
changeset 31497 4a6b2e733c0d
parent 25868 686eef1e7a79
child 35800 6041f8d71ed1
equal deleted inserted replaced
31302:f66c18528472 31497:4a6b2e733c0d
    24 import java.io.OutputStream;
    24 import java.io.OutputStream;
    25 import java.io.OutputStreamWriter;
    25 import java.io.OutputStreamWriter;
    26 import java.io.UnsupportedEncodingException;
    26 import java.io.UnsupportedEncodingException;
    27 import java.io.Writer;
    27 import java.io.Writer;
    28 import com.sun.org.apache.xerces.internal.util.EncodingMap;
    28 import com.sun.org.apache.xerces.internal.util.EncodingMap;
       
    29 import java.nio.charset.Charset;
       
    30 import java.nio.charset.CharsetEncoder;
    29 
    31 
    30 /**
    32 /**
    31  * This class represents an encoding.
    33  * This class represents an encoding.
    32  *
    34  *
    33  * @deprecated As of JDK 1.9, Xerces 2.9.0, Xerces DOM L3 Serializer implementation
    35  * @deprecated As of JDK 1.9, Xerces 2.9.0, Xerces DOM L3 Serializer implementation
    35  * {@link com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl} is replaced
    37  * {@link com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl} is replaced
    36  * by {@link com.sun.org.apache.xml.internal.serializer.dom3.LSSerializerImpl}.
    38  * by {@link com.sun.org.apache.xml.internal.serializer.dom3.LSSerializerImpl}.
    37  */
    39  */
    38 public class EncodingInfo {
    40 public class EncodingInfo {
    39 
    41 
    40     // An array to hold the argument for a method of Charset, CharsetEncoder or CharToByteConverter.
       
    41     private Object [] fArgsForMethod = null;
       
    42 
       
    43     // name of encoding as registered with IANA;
    42     // name of encoding as registered with IANA;
    44     // preferably a MIME name, but aliases are fine too.
    43     // preferably a MIME name, but aliases are fine too.
    45     String ianaName;
    44     String ianaName;
    46     String javaName;
    45     String javaName;
    47     int lastPrintable;
    46     int lastPrintable;
    48 
    47 
    49     // The CharsetEncoder with which we test unusual characters.
    48     // The CharsetEncoder with which we test unusual characters.
    50     Object fCharsetEncoder = null;
    49     CharsetEncoder fCharsetEncoder = null;
    51 
       
    52     // The CharToByteConverter with which we test unusual characters.
       
    53     Object fCharToByteConverter = null;
       
    54 
       
    55     // Is the converter null because it can't be instantiated
       
    56     // for some reason (perhaps we're running with insufficient authority as
       
    57     // an applet?
       
    58     boolean fHaveTriedCToB = false;
       
    59 
    50 
    60     // Is the charset encoder usable or available.
    51     // Is the charset encoder usable or available.
    61     boolean fHaveTriedCharsetEncoder = false;
    52     boolean fHaveTriedCharsetEncoder = false;
    62 
    53 
    63     /**
    54     /**
   116      * @param ch a code point (0-0x10ffff)
   107      * @param ch a code point (0-0x10ffff)
   117      */
   108      */
   118     private boolean isPrintable0(char ch) {
   109     private boolean isPrintable0(char ch) {
   119 
   110 
   120         // Attempt to get a CharsetEncoder for this encoding.
   111         // Attempt to get a CharsetEncoder for this encoding.
   121         if (fCharsetEncoder == null && CharsetMethods.fgNIOCharsetAvailable && !fHaveTriedCharsetEncoder) {
   112         if (fCharsetEncoder == null && !fHaveTriedCharsetEncoder) {
   122             if (fArgsForMethod == null) {
       
   123                 fArgsForMethod = new Object [1];
       
   124             }
       
   125             // try and create the CharsetEncoder
   113             // try and create the CharsetEncoder
   126             try {
   114             try {
   127                 fArgsForMethod[0] = javaName;
   115                 Charset charset = java.nio.charset.Charset.forName(javaName);
   128                 Object charset = CharsetMethods.fgCharsetForNameMethod.invoke(null, fArgsForMethod);
   116                 if (charset.canEncode()) {
   129                 if (((Boolean) CharsetMethods.fgCharsetCanEncodeMethod.invoke(charset, (Object[]) null)).booleanValue()) {
   117                     fCharsetEncoder = charset.newEncoder();
   130                     fCharsetEncoder = CharsetMethods.fgCharsetNewEncoderMethod.invoke(charset, (Object[]) null);
       
   131                 }
   118                 }
   132                 // This charset cannot be used for encoding, don't try it again...
   119                 // This charset cannot be used for encoding, don't try it again...
   133                 else {
   120                 else {
   134                     fHaveTriedCharsetEncoder = true;
   121                     fHaveTriedCharsetEncoder = true;
   135                 }
   122                 }
   140             }
   127             }
   141         }
   128         }
   142         // Attempt to use the CharsetEncoder to determine whether the character is printable.
   129         // Attempt to use the CharsetEncoder to determine whether the character is printable.
   143         if (fCharsetEncoder != null) {
   130         if (fCharsetEncoder != null) {
   144             try {
   131             try {
   145                 fArgsForMethod[0] = new Character(ch);
   132                 return fCharsetEncoder.canEncode(ch);
   146                 return ((Boolean) CharsetMethods.fgCharsetEncoderCanEncodeMethod.invoke(fCharsetEncoder, fArgsForMethod)).booleanValue();
       
   147             }
   133             }
   148             catch (Exception e) {
   134             catch (Exception e) {
   149                 // obviously can't use this charset encoder; possibly a JDK bug
   135                 // obviously can't use this charset encoder; possibly a JDK bug
   150                 fCharsetEncoder = null;
   136                 fCharsetEncoder = null;
   151                 fHaveTriedCharsetEncoder = false;
   137                 fHaveTriedCharsetEncoder = false;
   152             }
   138             }
   153         }
   139         }
   154 
   140 
   155         // As a last resort try to use a sun.io.CharToByteConverter to
   141         return false;
   156         // determine whether this character is printable. We will always
       
   157         // reach here on JDK 1.3 or below.
       
   158         if (fCharToByteConverter == null) {
       
   159             if (fHaveTriedCToB || !CharToByteConverterMethods.fgConvertersAvailable) {
       
   160                 // forget it; nothing we can do...
       
   161                 return false;
       
   162             }
       
   163             if (fArgsForMethod == null) {
       
   164                 fArgsForMethod = new Object [1];
       
   165             }
       
   166             // try and create the CharToByteConverter
       
   167             try {
       
   168                 fArgsForMethod[0] = javaName;
       
   169                 fCharToByteConverter = CharToByteConverterMethods.fgGetConverterMethod.invoke(null, fArgsForMethod);
       
   170             }
       
   171             catch (Exception e) {
       
   172                 // don't try it again...
       
   173                 fHaveTriedCToB = true;
       
   174                 return false;
       
   175             }
       
   176         }
       
   177         try {
       
   178             fArgsForMethod[0] = new Character(ch);
       
   179             return ((Boolean) CharToByteConverterMethods.fgCanConvertMethod.invoke(fCharToByteConverter, fArgsForMethod)).booleanValue();
       
   180         }
       
   181         catch (Exception e) {
       
   182             // obviously can't use this converter; probably some kind of
       
   183             // security restriction
       
   184             fCharToByteConverter = null;
       
   185             fHaveTriedCToB = false;
       
   186             return false;
       
   187         }
       
   188     }
   142     }
   189 
   143 
   190     // is this an encoding name recognized by this JDK?
   144     // is this an encoding name recognized by this JDK?
   191     // if not, will throw UnsupportedEncodingException
   145     // if not, will throw UnsupportedEncodingException
   192     public static void testJavaEncodingName(String name)  throws UnsupportedEncodingException {
   146     public static void testJavaEncodingName(String name)  throws UnsupportedEncodingException {
   193         final byte [] bTest = {(byte)'v', (byte)'a', (byte)'l', (byte)'i', (byte)'d'};
   147         final byte [] bTest = {(byte)'v', (byte)'a', (byte)'l', (byte)'i', (byte)'d'};
   194         String s = new String(bTest, name);
   148         String s = new String(bTest, name);
   195     }
   149     }
   196 
   150 
   197     /**
       
   198      * Holder of methods from java.nio.charset.Charset and java.nio.charset.CharsetEncoder.
       
   199      */
       
   200     static class CharsetMethods {
       
   201 
       
   202         // Method: java.nio.charset.Charset.forName(java.lang.String)
       
   203         private static java.lang.reflect.Method fgCharsetForNameMethod = null;
       
   204 
       
   205         // Method: java.nio.charset.Charset.canEncode()
       
   206         private static java.lang.reflect.Method fgCharsetCanEncodeMethod = null;
       
   207 
       
   208         // Method: java.nio.charset.Charset.newEncoder()
       
   209         private static java.lang.reflect.Method fgCharsetNewEncoderMethod = null;
       
   210 
       
   211         // Method: java.nio.charset.CharsetEncoder.canEncode(char)
       
   212         private static java.lang.reflect.Method fgCharsetEncoderCanEncodeMethod = null;
       
   213 
       
   214         // Flag indicating whether or not java.nio.charset.* is available.
       
   215         private static boolean fgNIOCharsetAvailable = false;
       
   216 
       
   217         private CharsetMethods() {}
       
   218 
       
   219         // Attempt to get methods for Charset and CharsetEncoder on class initialization.
       
   220         static {
       
   221             try {
       
   222                 Class charsetClass = Class.forName("java.nio.charset.Charset");
       
   223                 Class charsetEncoderClass = Class.forName("java.nio.charset.CharsetEncoder");
       
   224                 fgCharsetForNameMethod = charsetClass.getMethod("forName", new Class [] {String.class});
       
   225                 fgCharsetCanEncodeMethod = charsetClass.getMethod("canEncode", new Class [] {});
       
   226                 fgCharsetNewEncoderMethod = charsetClass.getMethod("newEncoder", new Class [] {});
       
   227                 fgCharsetEncoderCanEncodeMethod = charsetEncoderClass.getMethod("canEncode", new Class [] {Character.TYPE});
       
   228                 fgNIOCharsetAvailable = true;
       
   229             }
       
   230             // ClassNotFoundException, NoSuchMethodException or SecurityException
       
   231             // Whatever the case, we cannot use java.nio.charset.*.
       
   232             catch (Exception exc) {
       
   233                 fgCharsetForNameMethod = null;
       
   234                 fgCharsetCanEncodeMethod = null;
       
   235                 fgCharsetEncoderCanEncodeMethod = null;
       
   236                 fgCharsetNewEncoderMethod = null;
       
   237                 fgNIOCharsetAvailable = false;
       
   238             }
       
   239         }
       
   240     }
       
   241 
       
   242     /**
       
   243      * Holder of methods from sun.io.CharToByteConverter.
       
   244      */
       
   245     static class CharToByteConverterMethods {
       
   246 
       
   247         // Method: sun.io.CharToByteConverter.getConverter(java.lang.String)
       
   248         private static java.lang.reflect.Method fgGetConverterMethod = null;
       
   249 
       
   250         // Method: sun.io.CharToByteConverter.canConvert(char)
       
   251         private static java.lang.reflect.Method fgCanConvertMethod = null;
       
   252 
       
   253         // Flag indicating whether or not sun.io.CharToByteConverter is available.
       
   254         private static boolean fgConvertersAvailable = false;
       
   255 
       
   256         private CharToByteConverterMethods() {}
       
   257 
       
   258         // Attempt to get methods for char to byte converter on class initialization.
       
   259         static {
       
   260             try {
       
   261                 Class clazz = Class.forName("sun.io.CharToByteConverter");
       
   262                 fgGetConverterMethod = clazz.getMethod("getConverter", new Class [] {String.class});
       
   263                 fgCanConvertMethod = clazz.getMethod("canConvert", new Class [] {Character.TYPE});
       
   264                 fgConvertersAvailable = true;
       
   265             }
       
   266             // ClassNotFoundException, NoSuchMethodException or SecurityException
       
   267             // Whatever the case, we cannot use sun.io.CharToByteConverter.
       
   268             catch (Exception exc) {
       
   269                 fgGetConverterMethod = null;
       
   270                 fgCanConvertMethod = null;
       
   271                 fgConvertersAvailable = false;
       
   272             }
       
   273         }
       
   274     }
       
   275 }
   151 }