1 16 package org.apache.cocoon.components.serializers.encoding; 17 18 import java.io.ByteArrayOutputStream ; 19 import java.io.File ; 20 import java.io.PrintWriter ; 21 import java.io.PrintStream ; 22 import java.io.IOException ; 23 import java.io.OutputStreamWriter ; 24 import java.io.UnsupportedEncodingException ; 25 import java.net.URL ; 26 import java.util.Enumeration ; 27 import java.util.HashMap ; 28 import java.util.zip.ZipEntry ; 29 import java.util.zip.ZipFile ; 30 31 37 public final class CharsetFactory { 38 39 40 private static final String CHARSET_LOOKUP_CLASS = 41 "org/apache/cocoon/components/serializers/encoding/cs_US_ASCII.class"; 42 43 44 private static CharsetFactory instance = new CharsetFactory(); 45 46 47 private Charset defaultCharset = null; 48 49 50 private Charset unknownCharset = null; 51 52 53 private HashMap charsets = new HashMap (); 54 55 58 private CharsetFactory() { 59 super(); 60 this.unknownCharset = new UnknownCharset(); 61 62 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 63 URL url = loader.getResource(CHARSET_LOOKUP_CLASS); 64 65 if (url == null) { 66 throw new CharsetFactoryException("Unable to load charsets " 67 + "because their classes are not present", null); 68 } 69 70 if ("jar".equals(url.getProtocol())) { 71 this.loadCharsetsFromJar(url); 72 } else if ("file".equals(url.getProtocol())) { 73 this.loadCharsetsFromFile(url); 74 } else { 75 throw new CharsetFactoryException("Unable to load charsets " + 76 "from protocol \"" + url.getProtocol() + "\"", null); 77 } 78 79 ByteArrayOutputStream otmp = new ByteArrayOutputStream (); 80 OutputStreamWriter wtmp = new OutputStreamWriter (otmp); 81 String etmp = wtmp.getEncoding(); 82 try { 83 defaultCharset = this.getCharset(etmp); 84 } catch (UnsupportedEncodingException exception) { 85 throw new CharsetFactoryException("The default encoding of this " 86 + "JVM \"" + etmp + "\" is not supported", exception); 87 } 88 89 } 90 91 94 private void loadCharset(Charset charset) { 95 this.charsets.put(charset.getName().toLowerCase(), charset); 96 String aliases[] = charset.getAliases(); 97 for (int x = 0; x < aliases.length; x++) { 98 this.charsets.put(aliases[x].toLowerCase(), charset); 99 } 100 } 101 102 105 private void loadCharset(String clazz) { 106 try { 107 Class c = Class.forName(clazz); 108 Object o = c.newInstance(); 109 if (o instanceof Charset) { 110 loadCharset((Charset)o); 111 } 112 } catch (Exception exception) { 113 throw new CharsetFactoryException("Unable to instantiate class \"" 114 + clazz + "\"", exception); 115 } 116 } 117 118 122 private void loadCharsetsFromJar(URL url) { 123 try { 124 String file = url.getFile(); 125 String mtch = file.substring(file.indexOf('!')); 126 file = file.substring(5, file.indexOf('!')); 127 mtch = mtch.substring(2, mtch.lastIndexOf('/') + 1) + "cs_"; 128 129 ZipFile zip = new ZipFile (file); 130 Enumeration enumeration = zip.entries(); 131 while (enumeration.hasMoreElements()) { 132 ZipEntry entry = (ZipEntry )enumeration.nextElement(); 133 String name = entry.getName(); 134 if ((! name.startsWith(mtch)) || 135 (! name.endsWith(".class"))) continue; 136 name = name.substring(mtch.length()); 137 name = ".cs_" + name.substring(0, name.length() - 6); 138 name = this.getClass().getPackage().getName() + name; 139 loadCharset(name); 140 } 141 } catch (IOException exception) { 142 throw new CharsetFactoryException("Unable to access JAR \"" 143 + url.toString() + "\"", exception); 144 } 145 } 146 147 151 private void loadCharsetsFromFile(URL url) { 152 File file = new File (url.getFile()).getParentFile(); 153 String children[] = file.list(); 154 for (int x = 0; x < children.length; x++) { 155 String child = children[x]; 156 if ((! child.startsWith("cs_")) || 157 (! child.endsWith(".class"))) continue; 158 child = '.' + child.substring(0, child.length() - 6); 159 child = this.getClass().getPackage().getName() + child; 160 this.loadCharset(child); 161 } 162 } 163 164 167 public static CharsetFactory newInstance() { 168 if (instance != null) return (instance); 169 synchronized (CharsetFactory.class) { 170 if (instance != null) return (instance); 171 instance = new CharsetFactory(); 172 } 173 return(instance); 174 } 175 176 182 public Charset getCharset() { 183 return(unknownCharset); 184 } 185 186 190 public Charset getDefaultCharset() { 191 return(defaultCharset); 192 } 193 194 200 public Charset getCharset(String name) 201 throws UnsupportedEncodingException { 202 if (name == null) return(this.getDefaultCharset()); 203 Charset charset = (Charset)this.charsets.get(name.toLowerCase()); 204 if (charset != null) return(charset); 205 throw new UnsupportedEncodingException ("Unsupported charset \"" 206 + name + "\""); 207 } 208 209 213 private static class CharsetFactoryException extends RuntimeException { 214 215 216 private Exception exception = null; 217 218 221 private CharsetFactoryException(String message, Exception exception) { 222 super(message == null? exception.getMessage(): message); 223 this.exception = exception; 224 } 225 226 229 public Exception getException() { 230 return(this.exception); 231 } 232 233 237 public void printStackTrace(PrintWriter out) { 238 super.printStackTrace(out); 239 if (this.exception != null) { 240 out.print("Root cause: "); 241 this.exception.printStackTrace(out); 242 } 243 } 244 245 249 public void printStackTrace(PrintStream out) { 250 super.printStackTrace(out); 251 if (this.exception != null) { 252 out.print("Root cause: "); 253 this.exception.printStackTrace(out); 254 } 255 } 256 } 257 } 258 | Popular Tags |