1 23 package org.enhydra.xml.io; 24 25 import java.io.BufferedReader ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.io.InputStreamReader ; 29 import java.lang.reflect.Constructor ; 30 import java.util.HashMap ; 31 import java.util.Iterator ; 32 import java.util.StringTokenizer ; 33 34 38 41 public final class Encodings { 42 45 public static final String ISO_8859_1 = "ISO_8859-1"; 46 public static final String US_ASCII = "US-ASCII"; 47 public static final String SHIFT_JIS = "Shift_JIS"; 48 49 52 private final String CHAR_SET_TABLE 53 = "org/enhydra/xml/io/character-sets.tbl"; 54 55 58 private final String NULL_STR = "null"; 59 60 63 private static Encodings fSingleton; 64 65 68 private static final String [] fEmptyAliases = new String [0]; 69 70 74 private final HashMap fCharSets = new HashMap (); 75 76 private static final Class CHARSET_CONSTRUCTOR_TYPES[] = { 77 String .class, Integer.TYPE, String .class, String [].class 78 }; 79 80 83 private void parseError(String msg, 84 String line) { 85 throw new XMLIOError(msg + "; parsing line in " + CHAR_SET_TABLE 86 + "\"" + line + "\""); 87 } 88 89 92 private CharacterSet parseCharSetEntry(String line) { 93 StringTokenizer tokens = new StringTokenizer (line); 94 int numTokens = tokens.countTokens(); 95 if (numTokens < 4) { 96 parseError("must have at least 4 entries", line); 97 } 98 99 String className = tokens.nextToken(); 100 String name = tokens.nextToken(); 101 Integer charSetSize = null; 102 try { 103 charSetSize = new Integer (tokens.nextToken()); 104 } catch (NumberFormatException nfe) { 105 parseError("invalid character set size", line); 106 } 107 String mimePreferred = tokens.nextToken();; 108 if (mimePreferred.equals(NULL_STR)) { 109 mimePreferred = null; 110 } 111 String [] aliases = fEmptyAliases; 112 113 if (numTokens > 4) { 114 aliases = new String [numTokens - 4]; 115 int idx = 0; 116 while (tokens.hasMoreTokens()) { 117 aliases[idx++] = tokens.nextToken(); 118 } 119 } 120 121 try { 123 Class clazz = Class.forName(className); 124 Constructor ctr = clazz.getConstructor(CHARSET_CONSTRUCTOR_TYPES); 125 Object params[] = { name, charSetSize, mimePreferred, aliases }; 126 return (CharacterSet)ctr.newInstance(params); 127 } catch (Exception e) { 128 parseError("Exception loading character set class '" + className + "': " + 129 e.toString(), line); 130 } 131 throw new IllegalStateException ("Ooops. This should never happen. Please debug"); 133 } 134 135 138 private void addEntry(CharacterSet charSet) { 139 fCharSets.put(charSet.getName().toUpperCase().intern(), charSet); 140 141 String [] aliases = charSet.getAliases(); 142 int len = (aliases == null) ? 0 : aliases.length; 143 for (int idx = 0; idx < len; idx++) { 144 fCharSets.put(aliases[idx].toUpperCase().intern(), charSet); 145 } 146 } 147 148 151 private void parseCharacterSetTable(BufferedReader in) throws IOException { 152 String line; 153 while ((line = in.readLine()) != null) { 154 addEntry(parseCharSetEntry(line)); 155 } 156 } 157 158 161 private void parseCharacterSetTable() { 162 ClassLoader loader = Encodings.class.getClassLoader(); 163 if (loader == null) { 164 loader = ClassLoader.getSystemClassLoader(); 166 } 167 InputStream inStream = loader.getResourceAsStream(CHAR_SET_TABLE); 168 if (inStream == null) { 169 throw new XMLIOError("can't find \"" + CHAR_SET_TABLE + "\" on class path"); 170 } 171 try { 172 try { 173 BufferedReader in = new BufferedReader (new InputStreamReader (inStream)); 174 parseCharacterSetTable(in); 175 } finally { 176 inStream.close(); 177 } 178 } catch (IOException except) { 179 throw new XMLIOError("error reading " + CHAR_SET_TABLE); 180 } 181 } 182 183 186 private Encodings() { 187 parseCharacterSetTable(); 188 } 189 190 193 public CharacterSet getCharacterSet(String encoding) { 194 return (CharacterSet)fCharSets.get(encoding.toUpperCase()); 195 } 196 197 200 public boolean isValid(String encoding) { 201 return getCharacterSet(encoding) != null; 202 } 203 204 208 public String getName(String encoding) { 209 CharacterSet charSet = getCharacterSet(encoding); 210 if (charSet == null) { 211 return null; 212 } else { 213 return charSet.getName(); 214 } 215 } 216 217 220 public String getMIMEPreferred(String encoding) { 221 CharacterSet charSet = getCharacterSet(encoding); 222 if (charSet == null) { 223 return null; 224 } else { 225 return charSet.getMIMEPreferred(); 226 } 227 } 228 229 233 public String [] getAliases(String encoding) { 234 CharacterSet charSet = getCharacterSet(encoding); 235 if (charSet == null) { 236 return null; 237 } else { 238 return charSet.getAliases(); 239 } 240 } 241 242 247 public int getMaxCharacterValue(String encoding) { 248 CharacterSet charSet = getCharacterSet(encoding); 249 if (charSet == null) { 250 return 0xFFFF; } else { 252 return charSet.getMaxCharValue(); 253 } 254 } 255 256 260 public boolean sameEncodings(String encoding1, 261 String encoding2) { 262 if ((encoding1 == null) && (encoding2 == null)) { 263 return true; 264 } else if ((encoding1 == null) || (encoding2 == null)) { 265 return false; 266 } else { 267 return (getCharacterSet(encoding1) == getCharacterSet(encoding2)); 268 } 269 } 270 271 274 public String toString() { 275 StringBuffer buf = new StringBuffer (4096); Iterator values = fCharSets.values().iterator(); 277 while (values.hasNext()) { 278 buf.append(values.next().toString()); 279 buf.append('\n'); 280 } 281 return buf.toString(); 282 } 283 284 287 public static Encodings getEncodings() { 288 if (fSingleton == null) { 289 fSingleton = new Encodings(); 290 } 291 return fSingleton; 292 } 293 } 294 | Popular Tags |