1 17 package org.columba.mail.folder; 18 19 import java.io.File ; 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.util.ArrayList ; 23 import java.util.Arrays ; 24 import java.util.Collections ; 25 import java.util.LinkedList ; 26 import java.util.List ; 27 import java.util.logging.Logger ; 28 29 import org.columba.core.base.ListTools; 30 import org.columba.core.filter.FilterList; 31 import org.columba.core.io.DiskIO; 32 import org.columba.core.xml.XmlElement; 33 import org.columba.mail.config.FolderItem; 34 import org.columba.mail.folder.headercache.BerkeleyDBHeaderList; 35 import org.columba.mail.folder.headercache.CachedHeaderfields; 36 import org.columba.mail.folder.headercache.SyncHeaderList; 37 import org.columba.mail.folder.search.DefaultSearchEngine; 38 import org.columba.mail.message.ColumbaHeader; 39 import org.columba.mail.message.ColumbaMessage; 40 import org.columba.mail.message.IColumbaHeader; 41 import org.columba.mail.message.IColumbaMessage; 42 import org.columba.mail.message.IHeaderList; 43 import org.columba.mail.message.IPersistantHeaderList; 44 import org.columba.ristretto.io.Source; 45 import org.columba.ristretto.io.SourceInputStream; 46 import org.columba.ristretto.message.Attributes; 47 import org.columba.ristretto.message.Flags; 48 import org.columba.ristretto.message.Header; 49 import org.columba.ristretto.message.LocalMimePart; 50 import org.columba.ristretto.message.MimeTree; 51 import org.columba.ristretto.parser.HeaderParser; 52 import org.columba.ristretto.parser.MessageParser; 53 import org.columba.ristretto.parser.ParserException; 54 55 76 public abstract class AbstractLocalFolder extends AbstractMessageFolder { 77 78 79 private static final Logger LOG = Logger 80 .getLogger("org.columba.mail.folder"); 81 82 85 protected int nextMessageUid = -1; 86 87 91 protected ColumbaMessage aktMessage; 92 93 private boolean firstOpen = true; 94 95 98 99 protected IDataStorage dataStorage; 100 101 protected IPersistantHeaderList headerList; 102 103 108 public AbstractLocalFolder(FolderItem item, String path) { 109 super(item, path); 110 111 XmlElement filterListElement = node.getElement(FilterList.XML_NAME); 114 115 if (filterListElement == null) { 116 filterListElement = new XmlElement(FilterList.XML_NAME); 119 getConfiguration().getRoot().addElement(filterListElement); 120 } 121 122 filterList = new FilterList(filterListElement); 123 124 setSearchEngine(new DefaultSearchEngine(this)); 125 } 126 127 133 public AbstractLocalFolder(String name, String type, String path) { 134 super(name, type, path); 135 136 XmlElement filterListElement = node.getElement(FilterList.XML_NAME); 138 139 if (filterListElement == null) { 140 filterListElement = new XmlElement(FilterList.XML_NAME); 143 getConfiguration().getRoot().addElement(filterListElement); 144 } 145 146 filterList = new FilterList(filterListElement); 147 148 setSearchEngine(new DefaultSearchEngine(this)); 149 } 150 151 156 public void removeFolder() throws Exception { 157 boolean b = DiskIO.deleteDirectory(directoryFile); 159 160 if (b) { 162 super.removeFolder(); 163 } 164 } 165 166 172 protected Object generateNextMessageUid() { 173 if (nextMessageUid == -1) { 174 try { 175 if (getHeaderList().count() > 0) { 176 List _headerList = new ArrayList (); 177 Object [] _uidList = headerList.getUids(); 178 for (int i = 0; i < _uidList.length; i++) { 179 _headerList.add(_uidList[i]); 180 } 181 Integer maxUid = (Integer ) Collections.max(_headerList); 182 nextMessageUid = maxUid.intValue() + 1; 183 } else { 184 nextMessageUid = 0; 185 } 186 } catch (Exception e) { 187 nextMessageUid = 0; 188 } 189 } 190 191 return new Integer (nextMessageUid++); 192 } 193 194 201 public void setNextMessageUid(int next) { 202 nextMessageUid = next; 203 } 204 205 212 public abstract IDataStorage getDataStorageInstance(); 213 214 217 public MimeTree getMimePartTree(Object uid) throws Exception { 218 IColumbaMessage message = getMessage(uid); 220 221 MimeTree mptree = message.getMimePartTree(); 223 224 return mptree; 225 } 226 227 228 public InputStream getMessageSourceStream(Object uid) throws Exception { 229 return getDataStorageInstance().getMessageStream(uid); 230 } 231 232 233 public InputStream getMimePartBodyStream(Object uid, Integer [] address) 234 throws Exception { 235 IColumbaMessage message = getMessage(uid); 237 238 LocalMimePart mimepart = (LocalMimePart) message.getMimePartTree() 240 .getFromAddress(address); 241 242 return mimepart.getInputStream(); 243 } 244 245 246 public InputStream getMimePartSourceStream(Object uid, Integer [] address) 247 throws Exception { 248 IColumbaMessage message = getMessage(uid); 250 251 LocalMimePart mimepart = (LocalMimePart) message.getMimePartTree() 253 .getFromAddress(address); 254 255 return new SourceInputStream(mimepart.getSource()); 256 } 257 258 267 public void innerCopy(IMailbox destFolder, Object [] uids) throws Exception { 268 if (getObservable() != null) { 269 getObservable().setMax(uids.length); 270 } 271 272 for (int i = 0; i < uids.length; i++) { 273 if (!exists(uids[i])) { 275 continue; 276 } 277 278 InputStream messageSourceStream = getMessageSourceStream(uids[i]); 279 destFolder.addMessage(messageSourceStream, getAttributes(uids[i]), 280 getFlags(uids[i])); 281 messageSourceStream.close(); 282 283 287 if (getObservable() != null) { 289 getObservable().setCurrent(i); 290 } 291 } 292 293 if (getObservable() != null) { 295 getObservable().resetCurrent(); 296 } 297 } 298 299 public Object addMessage(InputStream in) throws Exception { 300 return addMessage(in, null, null); 301 } 302 303 public Object addMessage(InputStream in, Attributes attributes, Flags flags) 304 throws Exception { 305 Object newUid = generateNextMessageUid(); 307 308 getDataStorageInstance().saveMessage(newUid, in); 310 311 in.close(); 313 314 Source source = getDataStorageInstance().getMessageSource(newUid); 316 int messageSize = source.length(); 317 318 Header header = HeaderParser.parse(source); 319 ColumbaHeader h; 320 if ((attributes != null) && (flags != null)) { 321 h = new ColumbaHeader(header, (Attributes) attributes.clone(), 323 new Flags(flags.getFlags())); 324 } else { 325 h = new ColumbaHeader(header); 326 h.set("columba.size", new Integer (messageSize / 1024)); 327 } 328 source.close(); 329 h.set("columba.uid", newUid); 330 getHeaderList().add(h, newUid); 331 332 fireMessageAdded(newUid, getFlags(newUid)); 333 return newUid; 334 } 335 336 337 public boolean isInboxFolder() { 338 return getId().equals("101"); 339 } 340 341 342 public boolean isTrashFolder() { 343 return getId().equals("105"); 344 } 345 346 347 public boolean supportsAddFolder(String newFolderType) { 348 return (FolderFactory.getInstance().getGroup(newFolderType).equals( 349 "local") || newFolderType.equals("VirtualFolder")); 350 } 351 352 357 public boolean supportsMove() { 358 return true; 359 } 360 361 366 protected ColumbaMessage getMessage(Object uid) throws Exception { 367 if (aktMessage != null) { 369 if (aktMessage.getUID().equals(uid)) { 370 return aktMessage; 372 } 373 } 374 375 ColumbaMessage message; 376 377 try { 378 379 Source source = null; 380 381 source = getDataStorageInstance().getMessageSource(uid); 382 383 try { 385 message = new ColumbaMessage(MessageParser.parse(source)); 386 } catch (ParserException e1) { 387 LOG.fine(e1.getSource().toString()); 388 throw e1; 389 } 390 source.close(); 391 392 message.setUID(uid); 393 394 aktMessage = message; 395 396 } catch (FolderInconsistentException e) { 398 super.removeMessage(uid); 399 400 throw e; 401 } 402 403 IColumbaHeader header = getHeaderList().get(uid); 406 header.setHeader(message.getHeader().getHeader()); 407 message.setHeader(header); 408 409 return message; 410 } 411 412 416 protected IColumbaHeader getMessageHeader(Object uid) throws Exception { 417 if ((aktMessage != null) && (aktMessage.getUID().equals(uid))) { 418 IColumbaMessage message = getMessage(uid); 423 424 int size = message.getHeader().count(); 426 427 IColumbaHeader h = getHeaderList().get(uid); 429 430 if (h == null) { 432 return null; 433 } 434 435 int cachedSize = h.count(); 437 438 if (size > cachedSize) { 440 return (ColumbaHeader) message.getHeader(); 441 } 442 443 return (ColumbaHeader) h; 444 } else { 445 return getHeaderList().get(uid); 448 } 449 } 450 451 454 public void removeMessage(Object uid) throws Exception { 455 getDataStorageInstance().removeMessage(uid); 457 458 super.removeMessage(uid); 460 461 } 462 463 475 protected void setFlags(Object uid, Flags flags) throws Exception { 476 IColumbaHeader h = getHeaderList().get(uid); 477 478 Flags oldFlags = h.getFlags(); 479 h.setFlags(flags); 480 481 if (oldFlags.get(Flags.RECENT) && !flags.get(Flags.RECENT)) { 483 getMessageFolderInfo().decRecent(); 484 } 485 486 if (!oldFlags.get(Flags.RECENT) && flags.get(Flags.RECENT)) { 487 getMessageFolderInfo().incRecent(); 488 } 489 490 if (oldFlags.get(Flags.SEEN) && !flags.get(Flags.SEEN)) { 491 getMessageFolderInfo().incUnseen(); 492 } 493 494 if (!oldFlags.get(Flags.SEEN) && flags.get(Flags.SEEN)) { 495 getMessageFolderInfo().decUnseen(); 496 } 497 } 498 499 507 public Header getHeaderFields(Object uid, String [] keys) throws Exception { 508 List cachedList = Arrays.asList(CachedHeaderfields 510 .getDefaultHeaderfields()); 511 512 LinkedList keyList = new LinkedList (Arrays.asList(keys)); 513 514 ListTools.substract(keyList, cachedList); 515 516 if (keyList.size() == 0) { 517 return getHeaderList().get(uid).getHeader(); 518 } else { 519 IColumbaMessage message = getMessage(uid); 522 523 Header header = message.getHeader().getHeader(); 524 525 Header subHeader = new Header(); 526 String value; 527 528 for (int i = 0; i < keys.length; i++) { 529 value = header.get(keys[i]); 530 531 if (value != null) { 532 subHeader.set(keys[i], value); 533 } 534 } 535 536 return subHeader; 537 } 538 } 539 540 543 public void expungeFolder() throws Exception { 544 if (aktMessage != null) { 548 aktMessage.close(); 549 aktMessage = null; 550 } 551 552 super.expungeFolder(); 553 } 554 555 558 public Header getAllHeaderFields(Object uid) throws Exception { 559 560 IColumbaMessage message = getMessage(uid); 561 562 Header header = message.getHeader().getHeader(); 563 564 return header; 565 } 566 567 public synchronized IHeaderList getHeaderList() throws Exception { 568 if (headerList == null) { 569 File headercacheDirectory = new File (getDirectoryFile(),"headerlist"); 571 headerList = new BerkeleyDBHeaderList(headercacheDirectory, getId()); 572 final AbstractMessageFolder folder = this; 573 headerList 574 .addHeaderListCorruptedListener(new IHeaderListCorruptedListener() { 575 576 public void headerListCorrupted(IHeaderList headerList) { 577 try { 578 SyncHeaderList.sync(folder, headerList); 579 } catch (IOException e) { 580 LOG.severe(e.getMessage()); 581 } 582 } 583 }); 584 } 585 586 if (firstOpen) { 587 588 if (headerList.count() != getDataStorageInstance() 589 .getMessageCount()) { 590 SyncHeaderList.sync(this, headerList); 592 } 593 594 firstOpen = false; 595 } 596 597 return headerList; 598 } 599 600 603 public void save() throws Exception { 604 super.save(); 605 if (headerList != null) 606 headerList.persist(); 607 } 608 609 614 protected void loadMessageFolderInfo() { 615 super.loadMessageFolderInfo(); 616 617 int storedCount = getDataStorageInstance().getMessageCount(); 618 if (messageFolderInfo.getExists() != storedCount) { 620 recreateMessageFolderInfo(); 621 } 622 623 } 624 } | Popular Tags |