1 19 package org.columba.mail.folder.imap; 20 21 import java.io.File ; 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.util.ArrayList ; 25 import java.util.Arrays ; 26 import java.util.Collections ; 27 import java.util.LinkedList ; 28 import java.util.List ; 29 import java.util.logging.Logger ; 30 31 import org.columba.api.command.IStatusObservable; 32 import org.columba.core.base.ListTools; 33 import org.columba.core.command.CommandCancelledException; 34 import org.columba.core.command.CommandProcessor; 35 import org.columba.core.connectionstate.ConnectionStateImpl; 36 import org.columba.core.xml.XmlElement; 37 import org.columba.mail.command.MailFolderCommandReference; 38 import org.columba.mail.config.FolderItem; 39 import org.columba.mail.config.IFolderItem; 40 import org.columba.mail.config.ImapItem; 41 import org.columba.mail.folder.AbstractRemoteFolder; 42 import org.columba.mail.folder.IHeaderListCorruptedListener; 43 import org.columba.mail.folder.IMailFolder; 44 import org.columba.mail.folder.IMailbox; 45 import org.columba.mail.folder.RootFolder; 46 import org.columba.mail.folder.command.ApplyFilterCommand; 47 import org.columba.mail.folder.headercache.BerkeleyDBHeaderList; 48 import org.columba.mail.folder.headercache.CachedHeaderfields; 49 import org.columba.mail.folder.search.DefaultSearchEngine; 50 import org.columba.mail.folder.search.IMAPQueryEngine; 51 import org.columba.mail.imap.IImapServer; 52 import org.columba.mail.message.ColumbaHeader; 53 import org.columba.mail.message.ICloseableIterator; 54 import org.columba.mail.message.IColumbaHeader; 55 import org.columba.mail.message.IHeaderList; 56 import org.columba.mail.message.IPersistantHeaderList; 57 import org.columba.mail.parser.PassiveHeaderParserInputStream; 58 import org.columba.mail.util.MailResourceLoader; 59 import org.columba.ristretto.imap.IMAPException; 60 import org.columba.ristretto.imap.IMAPFlags; 61 import org.columba.ristretto.imap.MailboxStatus; 62 import org.columba.ristretto.imap.SearchKey; 63 import org.columba.ristretto.imap.SequenceEntry; 64 import org.columba.ristretto.imap.SequenceSet; 65 import org.columba.ristretto.message.Attributes; 66 import org.columba.ristretto.message.Flags; 67 import org.columba.ristretto.message.Header; 68 import org.columba.ristretto.message.MimeTree; 69 70 public class IMAPFolder extends AbstractRemoteFolder { 71 72 73 private static final Logger LOG = Logger 74 .getLogger("org.columba.mail.folder.imap"); 75 76 79 private IImapServer store; 80 81 private IStatusObservable observable; 82 83 86 protected boolean existsOnServer = true; 87 88 private boolean readOnly; 89 90 private IPersistantHeaderList headerList; 91 92 private boolean firstSync = true; 93 94 private boolean mailboxSyncEnabled = true; 95 96 99 public boolean isReadOnly() { 100 return readOnly; 101 } 102 103 107 public IMAPFolder(IPersistantHeaderList headerList, IImapServer server) { 108 super("test", "IMAPFolder", "/tmp/"); 109 this.headerList = headerList; 110 this.observable = new DummyObservable(); 111 112 store = server; 113 } 114 115 118 public IMAPFolder(FolderItem folderItem, String path) { 119 super(folderItem, path); 120 121 DefaultSearchEngine engine = new DefaultSearchEngine(this); 122 engine.setNonDefaultEngine(new IMAPQueryEngine(this)); 123 setSearchEngine(engine); 124 125 } 126 127 130 public IMAPFolder(String name, String type, String path) throws Exception { 132 super(name, type, path); 133 134 IFolderItem item = getConfiguration(); 135 item.setString("property", "accessrights", "user"); 136 item.setString("property", "subfolder", "true"); 137 } 138 139 142 public void removeFolder() throws Exception { 143 try { 144 if (existsOnServer) { 145 String path = getImapPath(); 146 147 getServer().deleteFolder(path); 148 } 149 150 super.removeFolder(); 151 } catch (Exception e) { 152 throw e; 153 } 154 } 155 156 public void setName(String name) throws Exception { 157 if (getName() == null) { super.setName(name); 159 return; 160 } 161 162 String oldPath = getImapPath(); 163 LOG.info("old path=" + oldPath); 164 165 String newPath = null; 166 167 if (getParent() instanceof IMAPFolder) { 168 newPath = ((IMAPFolder) getParent()).getImapPath(); 169 } 170 171 newPath += (getServer().getDelimiter() + name); 172 LOG.info("new path=" + newPath); 173 174 getServer().renameFolder(oldPath, newPath); 175 super.setName(name); 176 } 177 178 183 public IImapServer getServer() { 184 if (store == null) { 185 store = ((IMAPRootFolder) getRootFolder()).getServer(); 186 } 187 188 return store; 189 } 190 191 194 public synchronized IHeaderList getHeaderList() throws Exception { 195 if (headerList == null) { 196 File headercacheDirectory = new File (getDirectoryFile(), 198 "headerlist"); 199 headerList = new BerkeleyDBHeaderList(headercacheDirectory, getId()); 200 201 headerList 202 .addHeaderListCorruptedListener(new IHeaderListCorruptedListener() { 203 204 public void headerListCorrupted(IHeaderList headerList) { 205 headerList.clear(); 206 getMessageFolderInfo().reset(); 207 fireFolderPropertyChanged(); 208 } 209 }); 210 211 } 212 213 if (mailboxSyncEnabled && ConnectionStateImpl.getInstance().isOnline() 214 && !getServer().isSelected(this)) { 215 CommandProcessor.getInstance().addOp( 217 new CheckForNewMessagesCommand( 218 new MailFolderCommandReference(this))); 219 } 220 221 return headerList; 222 } 223 224 protected ImapItem getImapItem() { 225 return getServer().getItem(); 226 } 227 228 protected void printStatusMessage(String message) { 229 if (getObservable() != null) { 230 getObservable().setMessage( 231 getImapItem().get("host") + ": " + message); 232 } 233 } 234 235 protected void setProgress(int progress) { 236 if (getObservable() != null) { 237 getObservable().setCurrent(progress); 238 } 239 } 240 241 protected void setMaximum(int progress) { 242 if (getObservable() != null) { 243 getObservable().setMax(progress); 244 } 245 } 246 247 253 Object [] synchronizeHeaderlist() throws Exception , IOException , 254 CommandCancelledException, IMAPException { 255 256 Object [] result = new Object [0]; 257 258 MailboxStatus status = getServer().getStatus(this); 260 261 if (status.getMessages() == 0) { 262 purgeHeaderList(); 263 264 syncMailboxInfo(status); 265 266 return result; 267 } 268 269 if (!firstSync 270 && status.getMessages() == this.getMessageFolderInfo() 271 .getExists()) { 272 return result; 273 } 274 275 List localUids = new LinkedList (Arrays 276 .asList(getHeaderList().getUids())); 277 Collections.sort(localUids); 279 280 int largestLocalUid = localUids.size() > 0 ? ((Integer ) localUids 281 .get(localUids.size() - 1)).intValue() : -1; 282 283 int largestRemoteUid = getServer().getLargestRemoteUid(this); 284 285 if (localUids.size() == status.getMessages() 286 && largestRemoteUid == largestLocalUid) { 287 if (firstSync) { 289 firstSync = false; 290 synchronizeFlags(status); 291 } else { 292 syncMailboxInfo(status); 293 } 294 295 return result; 296 } 297 298 printStatusMessage(MailResourceLoader.getString("statusbar", "message", 299 "sync_messages")); 300 301 largestRemoteUid = getServer().fetchUid( 302 new SequenceSet(SequenceEntry.STAR), this); 303 304 if (largestRemoteUid == -1) { 305 largestRemoteUid = getServer().fetchUid( 306 new SequenceSet(status.getMessages()), this); 307 } 308 309 int largestLocalUidIndex = findLargestLocalUidIndex(localUids); 310 311 int newMessages = status.getMessages() - largestLocalUidIndex; 312 313 326 LOG.fine("Found " + newMessages + " new Messages"); 327 328 if (newMessages > 0) { 330 printStatusMessage(MailResourceLoader.getString("statusbar", 331 "message", "fetch_new_headers")); 332 333 getMessageFolderInfo().setExists(localUids.size()); 335 getMessageFolderInfo().setUnseen( 336 Math.min(getMessageFolderInfo().getUnseen(), localUids 337 .size())); 338 getMessageFolderInfo().setRecent(0); 339 340 List newUids = fetchNewMessages(largestLocalUidIndex); 341 342 localUids.addAll(newUids); 343 344 if (newUids.size() < newMessages) { 345 CommandProcessor.getInstance().addOp( 348 new FetchMessagesCommand( 349 new MailFolderCommandReference(this), 350 newMessages, largestLocalUidIndex, newUids 351 .size())); 352 353 } else { 354 fetchDone(); 355 } 356 357 result = newUids.toArray(new Object [0]); 358 } else { 359 360 findRemovedMessages(status, localUids); 364 365 if (firstSync) { 366 firstSync = false; 367 synchronizeFlags(status); 368 } else { 369 syncMailboxInfo(status); 370 } 371 } 372 373 return result; 374 } 375 376 private int findLargestLocalUidIndex(List localUids) throws IOException , 377 IMAPException, CommandCancelledException { 378 int largestLocalUidIndex = -1; 379 380 printStatusMessage(MailResourceLoader.getString("statusbar", "message", 381 "sync_messages")); 382 383 if (localUids.size() > 0) { 385 int position = localUids.size() - 1; 387 while (largestLocalUidIndex == -1 388 && position >= localUids.size() - 10 && position >= 0) { 389 largestLocalUidIndex = getServer().getIndex( 390 (Integer ) localUids.get(position--), this); 391 } 392 393 if (largestLocalUidIndex == -1) { 395 int a, b, c; 396 int index; 397 a = 0; 398 b = position; 399 while (b > a && b - a > 1) { 400 c = Math.round((b - a) * 0.5f) + a; 401 402 index = getServer().getIndex((Integer ) localUids.get(c), 403 this); 404 if (index == -1) { 405 b = c; 406 } else { 407 a = c; 408 largestLocalUidIndex = index; 409 } 410 } 411 412 } else { 414 } 417 418 if (largestLocalUidIndex == -1) { 420 largestLocalUidIndex = 0; 422 } 423 424 } else { 425 largestLocalUidIndex = 0; 427 } 428 return largestLocalUidIndex; 429 } 430 431 private void findRemovedMessages(MailboxStatus status, List localUids) 432 throws Exception , IOException , IMAPException, 433 CommandCancelledException { 434 int largestRemoteUid = getServer().getLargestRemoteUid(this); 435 436 int deletedMessages = localUids.size() - status.getMessages(); 437 438 LOG.fine("Found " + deletedMessages + " deleted Messages"); 439 440 if (deletedMessages > 0) { 442 int found = 0; 443 while (localUids.size() > 0 446 && found != deletedMessages 447 && ((Integer ) localUids.get(localUids.size() - 1)) 448 .intValue() > largestRemoteUid) { 449 Flags flags = getHeaderList().remove( 450 localUids.get(localUids.size() - 1)).getFlags(); 451 fireMessageRemoved(localUids.remove(localUids.size() - 1), 452 flags); 453 454 found++; 455 } 456 457 461 int packSize = Math.min(Math.max(deletedMessages, status 463 .getMessages() / 10), 200); 464 465 int upper = status.getMessages(); 466 467 int localPointer = localUids.size() - 1; 468 469 while (upper >= 1 && found != deletedMessages) { 471 SequenceSet set = new SequenceSet(); 472 set.add(Math.max(upper - packSize + 1, 1), upper); 473 474 Integer [] actUids = getServer().fetchUids(set, this); 477 478 for (int i = actUids.length - 1; i >= 0 480 && found != deletedMessages; i--) { 481 482 while (found != deletedMessages && localPointer >= 0 484 && !localUids.get(localPointer).equals(actUids[i])) { 485 getHeaderList().remove(localUids.get(localPointer)); 488 489 found++; 490 localPointer--; 491 } 492 493 localPointer--; 495 } 496 497 upper = upper - packSize; 498 } 499 500 while (found < deletedMessages && localPointer >= 0) { 502 getHeaderList().remove(localUids.get(localPointer--)); 503 found++; 504 } 505 506 if (found != deletedMessages) { 507 LOG.severe("Assertion failed : found only " + found + " of " 508 + deletedMessages); 509 } 510 511 } 512 } 513 514 private void purgeHeaderList() throws Exception { 515 ICloseableIterator it = getHeaderList().keyIterator(); 516 while (it.hasNext()) { 517 Object uid = it.next(); 518 fireMessageRemoved(uid, getHeaderList().get(uid).getFlags()); 519 } 520 it.close(); 521 getHeaderList().clear(); 522 523 getMessageFolderInfo().reset(); 524 fireFolderPropertyChanged(); 525 } 526 527 List fetchNewMessages(int startIndex) throws IOException , IMAPException, 528 CommandCancelledException, Exception { 529 IMAPFlags[] newFlags = getServer().fetchFlagsListStartFrom2( 530 startIndex + 1, this); 531 532 List newUids = new ArrayList (newFlags.length); 533 534 for (int i = 0; i < newFlags.length; i++) { 536 newUids.add(newFlags[i].getUid()); 538 } 539 540 getServer().fetchHeaderList(getHeaderList(), newUids, this); 542 543 setFlags(newFlags); 545 546 for (int i = 0; i < newFlags.length; i++) { 548 fireMessageAdded(newFlags[i].getUid(), newFlags[i]); 549 } 550 551 return newUids; 552 } 553 554 private void syncMailboxInfo(MailboxStatus status) { 555 boolean updated = false; 556 if (status.getMessages() != -1 557 && messageFolderInfo.getExists() != status.getMessages()) { 558 messageFolderInfo.setExists(status.getMessages()); 559 updated = true; 560 } 561 562 if (status.getMessages() == 0) { 563 messageFolderInfo.setRecent(0); 564 messageFolderInfo.setUnseen(0); 565 updated = true; 566 } else { 567 568 if (status.getUnseen() != -1 569 && messageFolderInfo.getUnseen() != status.getUnseen()) { 570 messageFolderInfo.setUnseen(status.getUnseen()); 571 updated = true; 572 } 573 } 574 575 if (messageFolderInfo.getRecent() < 0) { 577 messageFolderInfo.setRecent(0); 578 updated = true; 579 } 580 if (messageFolderInfo.getRecent() > messageFolderInfo.getExists()) { 581 messageFolderInfo.setRecent(messageFolderInfo.getExists()); 582 updated = true; 583 } 584 585 if (messageFolderInfo.getUnseen() < 0) { 586 messageFolderInfo.setUnseen(0); 587 updated = true; 588 } 589 if (messageFolderInfo.getUnseen() > messageFolderInfo.getExists()) { 590 messageFolderInfo.setUnseen(messageFolderInfo.getExists()); 591 updated = true; 592 } 593 594 if (updated) { 595 fireFolderPropertyChanged(); 596 } 597 598 } 599 600 private void synchronizeFlags(MailboxStatus status) throws Exception , 601 IOException , CommandCancelledException, IMAPException { 602 printStatusMessage(MailResourceLoader.getString("statusbar", "message", 603 "sync_flags")); 604 605 MailboxStatus flagStatus = new MailboxStatus(); 606 flagStatus.setMessages(status.getMessages()); 607 608 SearchKey unseenKey = new SearchKey(SearchKey.UNSEEN); 611 List remoteUnseenUids = Arrays.asList(getServer().search(unseenKey, 612 this)); 613 flagStatus.setUnseen(remoteUnseenUids.size()); 614 615 SearchKey flaggedKey = new SearchKey(SearchKey.FLAGGED); 616 List remoteFlaggedUids = Arrays.asList(getServer().search(flaggedKey, 617 this)); 618 619 SearchKey deletedKey = new SearchKey(SearchKey.DELETED); 620 List remoteDeletedUids = Arrays.asList(getServer().search(deletedKey, 621 this)); 622 623 SearchKey recentKey = new SearchKey(SearchKey.RECENT); 624 List remoteRecentUids = Arrays.asList(getServer().search(recentKey, 625 this)); 626 flagStatus.setRecent(remoteRecentUids.size()); 627 628 SearchKey junkKey = new SearchKey(SearchKey.KEYWORD, "JUNK"); 629 List remoteJunkUids = Arrays.asList(getServer().search(junkKey, this)); 630 631 ICloseableIterator headerIterator = getHeaderList().headerIterator(); 633 634 int unseen = 0; 635 int flagged = 0; 636 int recent = 0; 637 int deleted = 0; 638 int junk = 0; 639 640 while (headerIterator.hasNext()) { 641 IColumbaHeader header = (IColumbaHeader) headerIterator.next(); 642 Object uid = header.get("columba.uid"); 643 644 Flags flag = header.getFlags(); 645 Flags oldFlag = (Flags) flag.clone(); 646 647 int index; 648 649 index = Collections.binarySearch(remoteUnseenUids, uid); 650 flag.setSeen(index < 0); 651 if (!flag.getSeen()) { 652 unseen++; 653 } 654 655 index = Collections.binarySearch(remoteDeletedUids, uid); 656 flag.setDeleted(index >= 0); 657 if (flag.getDeleted()) { 658 deleted++; 659 } 660 661 index = Collections.binarySearch(remoteFlaggedUids, uid); 662 flag.setFlagged(index >= 0); 663 if (flag.getFlagged()) { 664 flagged++; 665 } 666 667 index = Collections.binarySearch(remoteRecentUids, uid); 668 flag.setRecent(index >= 0); 669 if (flag.getRecent()) { 670 recent++; 671 } 672 673 index = Collections.binarySearch(remoteJunkUids, uid); 674 header.getAttributes().put("columba.spam", new Boolean (index >= 0)); 675 if (index >= 0) { 676 junk++; 677 } 678 679 if (!flag.equals(oldFlag)) { 680 getHeaderList().update(uid, header); 681 682 fireMessageFlagChanged(uid, oldFlag, 0); 683 } 684 } 685 headerIterator.close(); 686 687 if (remoteJunkUids.size() != junk || remoteRecentUids.size() != recent 688 || remoteFlaggedUids.size() != flagged 689 || remoteDeletedUids.size() != deleted 690 || remoteUnseenUids.size() != unseen) { 691 694 synchronizeHeaderlist(); 695 return; 696 } 697 698 syncMailboxInfo(flagStatus); 699 } 700 701 706 protected void setFlags(Flags[] flagsList) throws Exception { 707 for (int i = 0; i < flagsList.length; i++) { 708 IMAPFlags flags = (IMAPFlags) flagsList[i]; 709 710 Integer uid = (Integer ) flags.getUid(); 711 712 IColumbaHeader header = getHeaderList().get(uid); 713 714 Flags localFlags = header.getFlags(); 715 716 localFlags.setFlags(flags.getFlags()); 717 718 header.getAttributes().put("columba.spam", 720 Boolean.valueOf(flags.get(IMAPFlags.JUNK))); 721 722 getHeaderList().update(uid, header); 723 } 724 } 725 726 730 public MimeTree getMimePartTree(Object uid) throws Exception { 731 MimeTree tree = IMAPCache.getInstance().getMimeTree(this, uid); 732 if (tree == null) { 733 tree = getServer().getMimeTree(uid, this); 734 IMAPCache.getInstance().addMimeTree(this, uid, tree); 735 } 736 737 return tree; 738 } 739 740 749 public void innerCopy(IMailbox destiny, Object [] uids) throws Exception { 750 IMAPFolder destFolder = (IMAPFolder) destiny; 751 IHeaderList srcHeaderList = getHeaderList(); 752 IPersistantHeaderList destHeaderList = (IPersistantHeaderList) destFolder 753 .getHeaderList(); 754 755 Object [] destUids = getServer().copy(destFolder, uids, this); 756 757 if (destUids.length < uids.length) { 758 LOG 759 .warning("Some messages could not be copied because they do not exist anymore!"); 760 } 761 762 if (destUids.length == 0) 765 return; 766 767 771 Integer largestDestUid = new Integer (-1); 772 ICloseableIterator it = destHeaderList.keyIterator(); 773 while (it.hasNext()) { 774 Integer uid = (Integer ) it.next(); 775 if (largestDestUid.compareTo(uid) < 0) { 776 largestDestUid = uid; 777 } 778 } 779 it.close(); 780 781 if (((Integer ) destUids[0]).intValue() == largestDestUid.intValue() + 1) { 782 int j = 0; 783 for (int i = 0; i < uids.length; i++) { 784 IColumbaHeader destHeader = srcHeaderList.get(uids[i]); 785 if (destHeader != null) { 787 destHeader = (IColumbaHeader) destHeader.clone(); 789 790 destHeader.set("columba.uid", destUids[j]); 791 destHeaderList.add(destHeader, destUids[j]); 792 793 IMAPFlags flags = new IMAPFlags(destHeader.getFlags() 795 .getFlags()); 796 flags.setUid(destUids[j]); 797 798 destFolder.fireMessageAdded(flags.getUid(), flags); 799 j++; 800 } 801 } 802 } 803 804 } 805 806 810 public void markMessage(Object [] uids, int variant) throws Exception { 811 getServer().markMessage(uids, variant, this); 812 813 super.markMessage(uids, variant); 814 } 815 816 820 public void expungeFolder() throws Exception { 821 try { 822 getServer().expunge(this); 823 super.expungeFolder(); 824 } catch (Exception e) { 825 throw e; 826 } 827 } 828 829 834 public IColumbaHeader getMessageHeader(Object uid) throws Exception { 835 return getHeaderList().get(uid); 836 } 837 838 843 public String getImapPath() throws IOException , IMAPException, 844 CommandCancelledException { 845 StringBuffer path = new StringBuffer (); 846 path.append(getName()); 847 848 IMailFolder child = this; 849 850 while (true) { 851 child = (IMailFolder) child.getParent(); 852 853 if (child instanceof IMAPRootFolder) { 854 break; 855 } 856 857 String n = ((IMAPFolder) child).getName(); 858 859 path.insert(0, n + getServer().getDelimiter()); 860 } 861 862 return path.toString(); 863 } 864 865 868 public static XmlElement getDefaultProperties() { 869 XmlElement props = new XmlElement("property"); 870 871 props.addAttribute("accessrights", "user"); 872 props.addAttribute("subfolder", "true"); 873 874 return props; 875 } 876 877 880 public boolean tryToGetLock(Object locker) { 881 IMailFolder root = getRootFolder(); 884 if (root == null) 885 throw new IllegalArgumentException ("IMAPRoot is null"); 886 887 return root.tryToGetLock(locker); 888 } 889 890 893 public void releaseLock(Object locker) { 894 IMailFolder root = getRootFolder(); 895 if (root == null) 896 throw new IllegalArgumentException ("IMAPRoot is null"); 897 898 root.releaseLock(locker); 899 } 900 901 906 public void addSubfolder(IMailFolder child) throws Exception { 907 if (child instanceof IMAPFolder) { 908 909 getServer().createMailbox(child.getName(), this); 910 } 911 912 super.addSubfolder(child); 913 } 914 915 920 public IStatusObservable getObservable() { 921 if (observable == null) { 922 observable = ((IMAPRootFolder) getRootFolder()).getObservable(); 923 } 924 925 return observable; 926 } 927 928 933 public Object addMessage(InputStream in, Attributes attributes, Flags flags) 934 throws Exception { 935 PassiveHeaderParserInputStream withHeaderInputStream = new PassiveHeaderParserInputStream( 936 in); 937 938 IMAPFlags imapFlags = new IMAPFlags(flags.getFlags()); 939 940 Integer uid = getServer() 941 .append(withHeaderInputStream, imapFlags, this); 942 943 if (((Boolean ) attributes.get("columba.spam")).booleanValue()) { 946 imapFlags.set(IMAPFlags.JUNK, true); 947 948 getServer().setFlags(new Object [] { uid }, imapFlags, this); 949 } 950 951 Header header = withHeaderInputStream.getHeader(); 953 954 IColumbaHeader cHeader = new ColumbaHeader(header, 956 (Attributes) attributes.clone(), imapFlags); 957 958 getHeaderList().add(cHeader, uid); 959 960 fireMessageAdded(uid, cHeader.getFlags()); 961 962 return uid; 963 } 964 965 971 public Header getHeaderFields(Object uid, String [] keys) throws Exception { 972 IColumbaHeader header = getHeaderList().get(uid); 974 975 if (header == null) 976 return new Header(); 977 978 List cachedList = Arrays.asList(CachedHeaderfields 980 .getDefaultHeaderfields()); 981 982 List keyList = new ArrayList (Arrays.asList(keys)); 983 ListTools.substract(keyList, cachedList); 984 985 if (keyList.size() > 0) { 986 return getServer().getHeaders(uid, keys, this); 987 } else { 988 return (Header) header.getHeader().clone(); 989 } 990 } 991 992 997 public InputStream getMessageSourceStream(Object uid) throws Exception { 998 return getServer().getMessageSourceStream(uid, this); 999 } 1000 1001 1007 public InputStream getMimePartSourceStream(Object uid, Integer [] address) 1008 throws Exception { 1009 return getServer().getMimePartSourceStream(uid, address, this); 1010 } 1011 1012 1018 public InputStream getMimePartBodyStream(Object uid, Integer [] address) 1019 throws Exception { 1020 InputStream result = IMAPCache.getInstance().getMimeBody(this, uid, 1021 address); 1022 if (result == null) { 1023 LOG.fine("Cache miss - fetching from server"); 1024 result = IMAPCache.getInstance().addMimeBody(this, uid, address, 1025 getServer().getMimePartBodyStream(uid, address, this)); 1026 } 1027 return result; 1028 } 1029 1030 1035 public boolean isInboxFolder() { 1036 RootFolder root = (RootFolder) getRootFolder(); 1037 1038 if (root != null) { 1039 return root.getInboxFolder() == this; 1040 } else { 1041 return false; 1042 } 1043 } 1044 1045 1050 public boolean isTrashFolder() { 1051 RootFolder root = (RootFolder) getRootFolder(); 1052 1053 if (root != null) { 1054 return root.getTrashFolder() == this; 1055 } else { 1056 return false; 1057 } 1058 } 1059 1060 1066 public Object addMessage(InputStream in) throws Exception { 1067 PassiveHeaderParserInputStream withHeaderInputStream = new PassiveHeaderParserInputStream( 1068 in); 1069 1070 Integer uid = getServer().append(withHeaderInputStream, this); 1071 1072 if (getServer().isSelected(this)) { 1073 Header header = withHeaderInputStream.getHeader(); 1075 ColumbaHeader h = new ColumbaHeader(header); 1076 getHeaderList().add(h, uid); 1077 1078 fireMessageAdded(uid, h.getFlags()); 1079 } else { 1080 if (mailboxSyncEnabled) { 1081 CommandProcessor.getInstance().addOp( 1083 new CheckForNewMessagesCommand( 1084 new MailFolderCommandReference(this))); 1085 } 1086 } 1087 1088 return uid; 1089 } 1090 1091 1094 1100 1101 1104 public DefaultSearchEngine getSearchEngine() { 1105 if (searchEngine == null) { 1106 searchEngine = new DefaultSearchEngine(this); 1107 searchEngine.setNonDefaultEngine(new IMAPQueryEngine(this)); 1108 } 1109 1110 return searchEngine; 1111 } 1112 1113 1116 public Header getAllHeaderFields(Object uid) throws Exception { 1117 return getServer().getAllHeaders(uid, this); 1118 1119 } 1120 1121 1124 public boolean supportsAddFolder(String folder) { 1125 return true; 1126 } 1127 1128 1137 public void updateFlag(IMAPFlags flag) throws Exception , 1138 CommandCancelledException { 1139 if (getServer().isSelected(this)) { 1140 Integer uid = new Integer (getServer().fetchUid( 1141 new SequenceSet(flag.getIndex()), this)); 1142 flag.setUid(uid); 1143 setFlags(new Flags[] { flag }); 1144 } 1145 } 1146 1147 1151 public void setReadOnly(boolean readOnly) { 1152 this.readOnly = readOnly; 1153 } 1154 1155 1160 public void save() throws Exception { 1161 super.save(); 1162 1163 if (headerList != null) 1164 headerList.persist(); 1165 } 1166 1167 void fetchDone() throws IOException , CommandCancelledException, 1168 IMAPException, Exception { 1169 MailboxStatus status = getServer().getStatus(this); 1170 1171 List localUids = new LinkedList (Arrays 1172 .asList(getHeaderList().getUids())); 1173 Collections.sort(localUids); 1175 1176 findRemovedMessages(status, localUids); 1179 1180 if (firstSync) { 1181 firstSync = false; 1182 synchronizeFlags(status); 1183 } else { 1184 syncMailboxInfo(status); 1185 } 1186 1187 ImapItem item = getServer().getItem(); 1189 1190 boolean applyFilter = item.getBooleanWithDefault( 1191 "automatically_apply_filter", false); 1192 1193 if (applyFilter) { 1198 CommandProcessor.getInstance() 1199 .addOp( 1200 new ApplyFilterCommand( 1201 new MailFolderCommandReference(this))); 1202 } 1203 1204 mailboxSyncEnabled = true; 1206 } 1207 1208 1211 public boolean isMailboxSyncEnabled() { 1212 return mailboxSyncEnabled; 1213 } 1214 1215 1219 public void setMailboxSyncEnabled(boolean mailboxSyncEnabled) { 1220 this.mailboxSyncEnabled = mailboxSyncEnabled; 1221 } 1222 1223} | Popular Tags |