1 16 package org.joda.time.tz; 17 18 import java.io.DataInputStream ; 19 import java.io.File ; 20 import java.io.FileInputStream ; 21 import java.io.IOException ; 22 import java.io.InputStream ; 23 import java.lang.ref.SoftReference ; 24 import java.util.Collections ; 25 import java.util.Map ; 26 import java.util.Set ; 27 import java.util.TreeMap ; 28 29 import org.joda.time.DateTimeZone; 30 31 40 public class ZoneInfoProvider implements Provider { 41 42 43 private final File iFileDir; 44 45 private final String iResourcePath; 46 47 private final ClassLoader iLoader; 48 49 private final Map iZoneInfoMap; 50 51 56 public ZoneInfoProvider(File fileDir) throws IOException { 57 if (fileDir == null) { 58 throw new IllegalArgumentException ("No file directory provided"); 59 } 60 if (!fileDir.exists()) { 61 throw new IOException ("File directory doesn't exist: " + fileDir); 62 } 63 if (!fileDir.isDirectory()) { 64 throw new IOException ("File doesn't refer to a directory: " + fileDir); 65 } 66 67 iFileDir = fileDir; 68 iResourcePath = null; 69 iLoader = null; 70 71 iZoneInfoMap = loadZoneInfoMap(openResource("ZoneInfoMap")); 72 } 73 74 81 public ZoneInfoProvider(String resourcePath) throws IOException { 82 this(resourcePath, null, false); 83 } 84 85 93 public ZoneInfoProvider(String resourcePath, ClassLoader loader) 94 throws IOException 95 { 96 this(resourcePath, loader, true); 97 } 98 99 103 private ZoneInfoProvider(String resourcePath, 104 ClassLoader loader, boolean favorSystemLoader) 105 throws IOException 106 { 107 if (resourcePath == null) { 108 throw new IllegalArgumentException ("No resource path provided"); 109 } 110 if (!resourcePath.endsWith("/")) { 111 resourcePath += '/'; 112 } 113 114 iFileDir = null; 115 iResourcePath = resourcePath; 116 117 if (loader == null && !favorSystemLoader) { 118 loader = getClass().getClassLoader(); 119 } 120 121 iLoader = loader; 122 123 iZoneInfoMap = loadZoneInfoMap(openResource("ZoneInfoMap")); 124 } 125 126 135 public synchronized DateTimeZone getZone(String id) { 136 if (id == null) { 137 return null; 138 } 139 140 Object obj = iZoneInfoMap.get(id); 141 if (obj == null) { 142 return null; 143 } 144 145 if (id.equals(obj)) { 146 return loadZoneData(id); 148 } 149 150 if (obj instanceof SoftReference ) { 151 DateTimeZone tz = (DateTimeZone)((SoftReference )obj).get(); 152 if (tz != null) { 153 return tz; 154 } 155 return loadZoneData(id); 157 } 158 159 return getZone((String )obj); 161 } 162 163 168 public synchronized Set getAvailableIDs() { 169 return Collections.unmodifiableSet(iZoneInfoMap.keySet()); 170 } 171 172 177 protected void uncaughtException(Exception ex) { 178 Thread t = Thread.currentThread(); 179 t.getThreadGroup().uncaughtException(t, ex); 180 } 181 182 189 private InputStream openResource(String name) throws IOException { 190 InputStream in; 191 if (iFileDir != null) { 192 in = new FileInputStream (new File (iFileDir, name)); 193 } else { 194 String path = iResourcePath.concat(name); 195 if (iLoader != null) { 196 in = iLoader.getResourceAsStream(path); 197 } else { 198 in = ClassLoader.getSystemResourceAsStream(path); 199 } 200 if (in == null) { 201 StringBuffer buf = new StringBuffer (40) 202 .append("Resource not found: \"") 203 .append(path) 204 .append("\" ClassLoader: ") 205 .append(iLoader != null ? iLoader.toString() : "system"); 206 throw new IOException (buf.toString()); 207 } 208 } 209 return in; 210 } 211 212 218 private DateTimeZone loadZoneData(String id) { 219 InputStream in = null; 220 try { 221 in = openResource(id); 222 DateTimeZone tz = DateTimeZoneBuilder.readFrom(in, id); 223 iZoneInfoMap.put(id, new SoftReference (tz)); 224 return tz; 225 } catch (IOException e) { 226 uncaughtException(e); 227 iZoneInfoMap.remove(id); 228 return null; 229 } finally { 230 try { 231 if (in != null) { 232 in.close(); 233 } 234 } catch (IOException e) { 235 } 236 } 237 } 238 239 246 private static Map loadZoneInfoMap(InputStream in) throws IOException { 247 Map map = new TreeMap (String.CASE_INSENSITIVE_ORDER); 248 DataInputStream din = new DataInputStream (in); 249 try { 250 readZoneInfoMap(din, map); 251 } finally { 252 try { 253 din.close(); 254 } catch (IOException e) { 255 } 256 } 257 map.put("UTC", new SoftReference (DateTimeZone.UTC)); 258 return map; 259 } 260 261 267 private static void readZoneInfoMap(DataInputStream din, Map zimap) throws IOException { 268 int size = din.readUnsignedShort(); 270 String [] pool = new String [size]; 271 for (int i=0; i<size; i++) { 272 pool[i] = din.readUTF().intern(); 273 } 274 275 size = din.readUnsignedShort(); 277 for (int i=0; i<size; i++) { 278 try { 279 zimap.put(pool[din.readUnsignedShort()], pool[din.readUnsignedShort()]); 280 } catch (ArrayIndexOutOfBoundsException e) { 281 throw new IOException ("Corrupt zone info map"); 282 } 283 } 284 } 285 286 } 287 | Popular Tags |