1 package org.columba.mail.pop3; 19 20 import java.io.File ; 21 import java.io.IOException ; 22 import java.io.InputStream ; 23 import java.util.Date ; 24 import java.util.Iterator ; 25 import java.util.LinkedList ; 26 import java.util.List ; 27 import java.util.logging.Logger ; 28 29 import org.columba.api.command.IStatusObservable; 30 import org.columba.api.command.IWorkerStatusController; 31 import org.columba.core.base.ListTools; 32 import org.columba.core.base.Lock; 33 import org.columba.core.command.CommandCancelledException; 34 import org.columba.core.command.ProgressObservedInputStream; 35 import org.columba.mail.config.AccountItem; 36 import org.columba.mail.config.MailConfig; 37 import org.columba.mail.config.PopItem; 38 import org.columba.mail.config.SpecialFoldersItem; 39 import org.columba.mail.folder.IMailbox; 40 import org.columba.mail.folder.headercache.BerkeleyDBHeaderList; 41 import org.columba.mail.gui.tree.FolderTreeModel; 42 import org.columba.mail.message.ColumbaHeader; 43 import org.columba.mail.message.ColumbaMessage; 44 import org.columba.mail.message.ICloseableIterator; 45 import org.columba.mail.message.IColumbaHeader; 46 import org.columba.mail.message.IHeaderList; 47 import org.columba.mail.message.IPersistantHeaderList; 48 import org.columba.ristretto.io.Source; 49 import org.columba.ristretto.io.TempSourceFactory; 50 import org.columba.ristretto.message.Header; 51 import org.columba.ristretto.parser.HeaderParser; 52 import org.columba.ristretto.parser.ParserException; 53 import org.columba.ristretto.pop3.MessageNotOnServerException; 54 import org.columba.ristretto.pop3.POP3Exception; 55 56 63 public class POP3Server { 64 65 private static final Logger LOG = Logger 66 .getLogger("org.columba.mail.folder.headercache"); 67 68 private static final long DAY_IN_MS = 24 * 60 * 60 * 1000; 69 70 private AccountItem accountItem; 71 72 private File file; 73 74 private POP3Store store; 75 76 protected IPersistantHeaderList headerList; 77 78 private Lock lock; 79 80 84 private boolean cacheChanged; 85 86 public POP3Server(AccountItem accountItem) { 87 this.accountItem = accountItem; 88 89 int uid = accountItem.getUid(); 90 91 file = new File (MailConfig.getInstance().getPOP3Directory(), 92 (new Integer (uid)).toString()); 93 94 PopItem item = accountItem.getPopItem(); 95 96 store = new POP3Store(item); 97 98 if(!this.getConfigFile().isDirectory()) this.getConfigFile().delete(); 99 File headercacheDirectory = new File (file, "pop3"+uid); 100 headerList = new BerkeleyDBHeaderList(headercacheDirectory, "pop3_" + uid, new POP3HeaderBinding()); 101 ((BerkeleyDBHeaderList)headerList).setKeyType(String .class); 102 103 lock = new Lock(); 104 105 setCacheChanged(false); 106 } 107 108 public void save() throws Exception { 109 headerList.persist(); 110 } 111 112 public File getConfigFile() { 113 return file; 114 } 115 116 public AccountItem getAccountItem() { 117 return accountItem; 118 } 119 120 public IMailbox getFolder() { 121 SpecialFoldersItem foldersItem = accountItem.getSpecialFoldersItem(); 122 String inboxStr = foldersItem.get("inbox"); 123 124 IMailbox f = (IMailbox) FolderTreeModel.getInstance().getFolder( 125 inboxStr); 126 127 return f; 128 } 129 130 public void logout() throws Exception { 131 getStore().logout(); 132 } 133 134 public List synchronize() throws Exception { 135 if (getHeaderList().count() == 0) { 136 LOG.severe(accountItem.getName() + " - POP3 Headerlist is empty!"); 137 } 138 139 141 LinkedList headerUids = new LinkedList (getHeaderList().keySet()); 142 143 List newUids = store.getUIDList(); 147 148 ListTools.substract(newUids, headerUids); 151 152 ListTools.substract(headerUids, store.getUIDList()); 155 156 Iterator it = headerUids.iterator(); 157 158 while (it.hasNext()) { 160 getHeaderList().remove(it.next()); 161 cacheChanged = true; 162 } 163 164 return newUids; 166 } 167 168 public void deleteMessage(Object uid) throws IOException , POP3Exception, 169 CommandCancelledException { 170 try { 171 store.deleteMessage(uid); 172 173 getHeaderList().remove(uid); 174 175 setCacheChanged(true); 177 } catch (POP3Exception e) { 178 if ((e instanceof MessageNotOnServerException) 179 || (e.getResponse() != null && e.getResponse().isERR())) { 180 getHeaderList().remove(uid); 182 setCacheChanged(true); 183 } else 184 throw e; 185 } 186 187 } 188 189 public void deleteMessagesOlderThan(Date date) throws IOException , 190 POP3Exception, CommandCancelledException { 191 LOG.info("Removing message older than " + date); 192 IHeaderList headerList = getHeaderList(); 193 ICloseableIterator it = headerList.headerIterator(); 194 while (it.hasNext()) { 195 IColumbaHeader header = (IColumbaHeader) it.next(); 196 if (((Date ) header.get("columba.date")).before(date)) { 197 deleteMessage(header.get("columba.uid")); 198 } 199 } 200 it.close(); 201 } 202 203 public void cleanUpServer() throws IOException , POP3Exception, 204 CommandCancelledException { 205 PopItem item = getAccountItem().getPopItem(); 206 207 if (item.getBooleanWithDefault("leave_messages_on_server", false) 208 && item.getBooleanWithDefault("remove_old_from_server", false)) { 209 int days = item.getInteger("older_than"); 210 long date = new Date ().getTime(); 211 date -= days * DAY_IN_MS; 212 213 deleteMessagesOlderThan(new Date (date)); 214 } else if (!item.getBooleanWithDefault("leave_messages_on_server", 215 false)) { 216 removeAllDownloadedMessages(); 217 } 218 } 219 220 private void removeAllDownloadedMessages() throws IOException , 221 CommandCancelledException, POP3Exception { 222 IHeaderList headerList = getHeaderList(); 223 ICloseableIterator it = headerList.keyIterator(); 224 while (it.hasNext()) { 225 deleteMessage(it.next()); 226 } 227 it.close(); 228 } 229 230 private IHeaderList getHeaderList() { 231 return headerList; 232 } 233 234 public int getMessageCount() throws Exception { 235 return getStore().getMessageCount(); 236 } 237 238 public ColumbaMessage getMessage(Object uid, IWorkerStatusController worker) 239 throws IOException , POP3Exception, CommandCancelledException, 240 ParserException { 241 InputStream messageStream = new ProgressObservedInputStream(getStore() 242 .fetchMessage(store.getIndex(uid)), worker, true); 243 244 Source source = TempSourceFactory.createTempSource(messageStream, -1); 246 247 ColumbaMessage m; 256 try { 257 Header header = HeaderParser.parse(source); 258 259 m = new ColumbaMessage(header); 260 ColumbaHeader h = (ColumbaHeader) m.getHeader(); 261 262 m.setSource(source); 263 h.getAttributes().put("columba.pop3uid", uid); 264 int size = Math.max(source.length() / 1024, 1); 266 h.getAttributes().put("columba.size", new Integer (size)); 267 268 h.getAttributes().put("columba.attachment", h.hasAttachments()); 270 h.getAttributes().put("columba.fetchstate", Boolean.TRUE); 271 h.getAttributes().put("columba.accountuid", 272 new Integer (accountItem.getInteger("uid"))); 273 274 getHeaderList().add(h, uid); 275 } catch (ParserException e) { 276 LOG 277 .severe("Skipped message: Error parsing message. Message source:\n " 278 + source); 279 return null; 280 } 281 282 setCacheChanged(true); 284 285 return m; 286 } 287 288 public int getMessageSize(Object uid) throws Exception { 289 return store.getSize(store.getIndex(uid)); 290 } 291 292 public String getFolderName() { 293 return accountItem.getName(); 294 } 295 296 301 public POP3Store getStore() { 302 return store; 303 } 304 305 public IStatusObservable getObservable() { 306 return store.getObservable(); 307 } 308 309 public boolean tryToGetLock(Object locker) { 310 return lock.tryToGetLock(locker); 311 } 312 313 public void releaseLock(Object locker) { 314 lock.release(locker); 315 } 316 317 320 public boolean isCacheChanged() { 321 return cacheChanged; 322 } 323 324 328 private void setCacheChanged(boolean hasChanged) { 329 this.cacheChanged = hasChanged; 330 } 331 332 335 public void updateConfig() { 336 PopItem item = accountItem.getPopItem(); 337 338 store = new POP3Store(item); 339 } 340 341 345 public void dropConnection() throws IOException { 346 store.dropConnection(); 347 } 348 } | Popular Tags |