1 21 22 package org.armedbear.j.mail; 23 24 import java.io.BufferedReader ; 25 import java.io.BufferedWriter ; 26 import java.io.IOException ; 27 import java.io.InputStream ; 28 import java.io.InputStreamReader ; 29 import java.io.OutputStream ; 30 import java.io.OutputStreamWriter ; 31 import java.io.UnsupportedEncodingException ; 32 import java.net.MalformedURLException ; 33 import java.util.Enumeration ; 34 import java.util.Iterator ; 35 import java.util.List ; 36 import java.util.Properties ; 37 import org.armedbear.j.Directories; 38 import org.armedbear.j.File; 39 import org.armedbear.j.FastStringBuffer; 40 import org.armedbear.j.Headers; 41 import org.armedbear.j.Log; 42 import org.armedbear.j.Utilities; 43 44 public final class ImapMessageCache 45 { 46 private static Properties catalog; 47 48 private final File cacheDirectory; 49 private final int uidValidity; 50 51 private ImapMessageCache(File cacheDirectory, int uidValidity) 52 { 53 this.cacheDirectory = cacheDirectory; 54 this.uidValidity = uidValidity; 55 } 56 57 public int getUidValidity() 58 { 59 return uidValidity; 60 } 61 62 public static ImapMessageCache getMessageCache(ImapMailbox mb) 63 { 64 File cacheDirectory = getCacheDirectory(mb); 65 if (cacheDirectory == null) 66 return null; 67 final int uidValidity = mb.getSession().getUidValidity(); 69 File file = File.getInstance(cacheDirectory, "uidvalidity"); 70 boolean ok = false; 71 if (file.isFile()) { 72 try { 73 BufferedReader reader = 74 new BufferedReader (new InputStreamReader (file.getInputStream())); 75 String s = reader.readLine(); 76 reader.close(); 77 int n = Integer.parseInt(s); 78 if (n == uidValidity) 79 ok = true; 80 else 81 Log.warn("getMessageCache UIDVALIDITY has changed"); 82 } 83 catch (Exception e) { 84 Log.error(e); 85 } 86 } 87 if (!ok) { 88 Log.debug("getMessageCache deleting old files"); 89 String [] files = cacheDirectory.list(); 90 for (int i = files.length-1; i >= 0; i--) 91 File.getInstance(cacheDirectory, files[i]).delete(); 92 Log.debug("getMessageCache writing UIDVALIDITY " + uidValidity); 93 try { 94 BufferedWriter writer = 95 new BufferedWriter (new OutputStreamWriter (file.getOutputStream())); 96 writer.write(String.valueOf(uidValidity)); 97 writer.flush(); 98 writer.close(); 99 } 100 catch (IOException e) { 101 Log.error(e); 102 } 103 } 104 return new ImapMessageCache(cacheDirectory, uidValidity); 105 } 106 107 public void store(int uid, String message, String encoding) 108 { 109 Log.debug("store encoding = |" + encoding + "|"); 110 if (encoding == null) 111 encoding = "ISO-8859-1"; 112 if (!cacheDirectory.isDirectory()) { 113 cacheDirectory.mkdirs(); 114 if (!cacheDirectory.isDirectory()) { 115 Log.error("ImapMessageCache.store can't create cache directory"); 116 return; 117 } 118 } 119 File file = 120 File.getInstance(cacheDirectory, String.valueOf(uid)); 121 if (file == null) 122 return; 123 if (file.isFile()) { 124 Log.debug("ImapMessageCache.store message is already cached"); 125 return; 126 } 127 try { 128 BufferedWriter writer = null; 129 writer = 130 new BufferedWriter (new OutputStreamWriter (file.getOutputStream(), 131 encoding)); 132 writer.write(message); 133 writer.flush(); 134 writer.close(); 135 } 136 catch (UnsupportedEncodingException e) { 137 Log.error(e); 138 } 139 catch (IOException e) { 140 Log.error(e); 141 } 142 } 143 144 public String getMessageText(int uid) 145 { 146 File file = 147 File.getInstance(cacheDirectory, String.valueOf(uid)); 148 if (file == null) 149 return null; 150 if (!file.isFile()) 151 return null; 152 FastStringBuffer sb = new FastStringBuffer(); 153 try { 154 BufferedReader reader = 155 new BufferedReader (new InputStreamReader (file.getInputStream())); 156 String s; 157 while ((s = reader.readLine()) != null) { 158 if (s.length() == 0) 159 break; 160 sb.append(s); 161 sb.append("\r\n"); 162 } 163 reader.close(); 164 } 165 catch (Exception e) { 166 Log.error(e); 167 } 168 Headers headers = Headers.parse(sb.toString()); 169 String charset = null; 170 String contentType = headers.getValue(Headers.CONTENT_TYPE); 171 if (contentType != null) 172 charset = Utilities.getCharsetFromContentType(contentType); 173 String encoding = Utilities.getEncodingFromCharset(charset); 174 sb.setLength(0); 175 try { 176 BufferedReader reader = 177 new BufferedReader (new InputStreamReader (file.getInputStream(), encoding)); 178 String s; 179 while ((s = reader.readLine()) != null) { 180 sb.append(s); 181 sb.append("\r\n"); 182 } 183 reader.close(); 184 } 185 catch (Exception e) { 186 Log.error(e); 187 } 188 if (sb.length() > 0) 189 return sb.toString(); 190 return null; 191 } 192 193 public void removeDeletedEntries(List mailboxEntries) 194 { 195 Log.debug("ImapMessageCache.removeDeletedEntries"); 196 long start = System.currentTimeMillis(); 197 Iterator it = mailboxEntries.iterator(); 198 while (it.hasNext()) { 199 ImapMailboxEntry entry = (ImapMailboxEntry) it.next(); 200 if (entry.isDeleted()) { 201 File file = File.getInstance(cacheDirectory, 202 String.valueOf(entry.getUid())); 203 if (file != null && file.isFile()) { 204 Log.debug("deleting " + file.netPath()); 205 file.delete(); 206 } 207 } 208 } 209 long elapsed = System.currentTimeMillis() - start; 210 Log.debug("ImapMessageCache.removeDeletedEntries " + elapsed + " ms"); 211 } 212 213 private static synchronized File getCacheDirectory(ImapMailbox mb) 214 { 215 final File parentDirectory = 216 File.getInstance(Directories.getMailDirectory(), "imap/cache"); 217 if (!parentDirectory.isDirectory()) { 218 parentDirectory.mkdirs(); 219 if (!parentDirectory.isDirectory()) { 220 Log.error("can't create IMAP cache directory"); 221 return null; 222 } 223 } 224 File catalogFile = File.getInstance(parentDirectory, "catalog"); 225 boolean modified = false; 226 if (catalog == null) { 227 catalog = new Properties (); 229 try { 230 if (catalogFile.isFile()) { 231 InputStream in = catalogFile.getInputStream(); 232 catalog.load(in); 233 in.close(); 234 } 235 } 236 catch (IOException e) { 237 Log.error(e); 238 } 239 Properties temp = new Properties (); 241 Enumeration keys = catalog.keys(); 242 while (keys.hasMoreElements()) { 243 String key = (String ) keys.nextElement(); 244 String value = (String ) catalog.get(key); 245 if (key.indexOf('@') < 0 || key.indexOf(':') < 0) { 246 try { 248 ImapURL url = new ImapURL(key); 249 temp.put(url.getCanonicalName(), value); 250 } 251 catch (MalformedURLException e) { 252 Log.error(e); 253 Log.debug("deleting cached messages for " + key); 254 File dir = 255 File.getInstance(parentDirectory, value); 256 if (dir != null && dir.isDirectory()) { 257 File[] files = dir.listFiles(); 258 if (files != null) { 259 for (int i = files.length-1; i >= 0; i--) { 260 Log.debug("deleting " + files[i]); 261 files[i].delete(); 262 } 263 } 264 Log.debug("removing directory " + dir); 265 dir.delete(); 266 } 267 } 268 modified = true; 269 } else 270 temp.put(key, value); 271 } 272 if (modified) 273 catalog = temp; 274 } 275 File cacheDirectory = null; 276 final String mailboxName = mb.getUrl().getCanonicalName(); 277 final String directoryName = catalog.getProperty(mailboxName); 278 if (directoryName == null) { 279 cacheDirectory = Utilities.getTempFile(parentDirectory); 281 if (cacheDirectory != null) { 282 boolean directoryExists = cacheDirectory.isDirectory(); 283 if (!directoryExists) { 284 cacheDirectory.mkdirs(); 285 directoryExists = cacheDirectory.isDirectory(); 286 } 287 if (directoryExists) { 288 catalog.put(mailboxName, cacheDirectory.getName()); 290 modified = true; 291 } else 292 cacheDirectory = null; 293 } 294 if (cacheDirectory == null) 295 Log.error("can't create IMAP cache directory"); 296 } else 297 cacheDirectory = File.getInstance(parentDirectory, directoryName); 298 if (modified) { 299 Log.debug("saving modified catalog"); 300 try { 301 OutputStream out = catalogFile.getOutputStream(); 302 catalog.save(out, null); 303 out.flush(); 304 out.close(); 305 } 306 catch (IOException e) { 307 Log.error(e); 308 } 309 } 310 return cacheDirectory; 311 } 312 } 313 | Popular Tags |