1 21 22 package org.armedbear.j.mail; 23 24 import java.util.ArrayList ; 25 import java.util.Collections ; 26 import java.util.Comparator ; 27 import java.util.Iterator ; 28 import java.util.List ; 29 import javax.swing.Icon ; 30 import javax.swing.SwingUtilities ; 31 import org.armedbear.j.Buffer; 32 import org.armedbear.j.Debug; 33 import org.armedbear.j.Dispatcher; 34 import org.armedbear.j.Display; 35 import org.armedbear.j.Editor; 36 import org.armedbear.j.EditorIterator; 37 import org.armedbear.j.FastStringBuffer; 38 import org.armedbear.j.History; 39 import org.armedbear.j.InputDialog; 40 import org.armedbear.j.Line; 41 import org.armedbear.j.Log; 42 import org.armedbear.j.MessageDialog; 43 import org.armedbear.j.Position; 44 import org.armedbear.j.ProgressNotifier; 45 import org.armedbear.j.Property; 46 import org.armedbear.j.PropertyList; 47 import org.armedbear.j.Sidebar; 48 import org.armedbear.j.Utilities; 49 import org.armedbear.j.View; 50 51 public abstract class Mailbox extends Buffer 52 { 53 public static final int SORT_BY_DATE_SENT = 0; 54 55 protected MailboxURL url; 56 57 boolean showFullHeaders; 58 boolean showRawText; 59 60 protected boolean dirty; 61 62 protected int unreadMessageCount; 63 protected int newMessageCount; 64 65 protected List entries; 66 67 private long lastCheckMillis; 68 69 private int sortBy = SORT_BY_DATE_SENT; 70 71 private MessageBuffer previewBuffer; 72 73 protected Mailbox() 74 { 75 } 76 77 protected Mailbox(MailboxURL url) 78 { 79 this.url = url; 80 PropertyList props = MailboxProperties.getProperties(url); 81 if (props != null) 82 properties.putAll(props); 83 } 84 85 public MessageBuffer getPreviewBuffer() 86 { 87 return previewBuffer; 88 } 89 90 public void setPreviewBuffer(MessageBuffer buf) 91 { 92 previewBuffer = buf; 93 } 94 95 public Buffer getSecondary() 96 { 97 return previewBuffer; 98 } 99 100 public final MailboxURL getUrl() 101 { 102 return url; 103 } 104 105 public final int getSortBy() 106 { 107 return sortBy; 108 } 109 110 public abstract String getName(); 111 112 public synchronized final void setEntries(List entries) 113 { 114 this.entries = entries; 115 } 116 117 public synchronized final long getLastCheckMillis() 118 { 119 return lastCheckMillis; 120 } 121 122 protected synchronized final void setLastCheckMillis(long when) 123 { 124 lastCheckMillis = when; 125 } 126 127 public synchronized long getLastErrorMillis() 128 { 129 return 0; 130 } 131 132 public abstract void getNewMessages(); 133 134 public void getNewMessages(boolean userInitiated) 135 { 136 } 137 138 public abstract void readMessage(Line line); 139 140 public void readMessageOtherWindow(Line line) 141 { 142 } 143 144 protected void activateMessageBuffer(Editor editor, 145 MessageBuffer messageBuffer, boolean useOtherWindow) 146 { 147 editor.makeNext(messageBuffer); 148 if (useOtherWindow) { 149 Buffer oldBuffer = null; 150 Editor ed = editor.getOtherEditor(); 151 if (ed != null) 152 oldBuffer = ed.getBuffer(); 153 messageBuffer.setTransient(true); 154 editor.activateInOtherWindow(messageBuffer, 155 messageBuffer.getSplit()); 156 previewBuffer = messageBuffer; 157 if (oldBuffer != null && oldBuffer != messageBuffer) { 158 if (oldBuffer.isTransient()) 159 oldBuffer.kill(); 160 } 161 } else 162 editor.activate(messageBuffer); 163 } 164 165 public abstract void createFolder(); 166 public abstract void deleteFolder(); 167 public abstract void saveToFolder(); 168 public abstract void moveToFolder(); 169 170 public abstract void delete(); 171 172 public abstract void undelete(); 173 174 public abstract void markRead(); 175 176 public abstract void markUnread(); 177 178 public void flag() 179 { 180 } 181 182 public abstract void setAnsweredFlag(MailboxEntry entry); 183 184 public final int getUnreadMessageCount() 185 { 186 return unreadMessageCount; 187 } 188 189 public final int getNewMessageCount() 190 { 191 return newMessageCount; 192 } 193 194 public void countMessages() 197 { 198 unreadMessageCount = newMessageCount = 0; 199 for (Line line = getFirstLine(); line != null; line = line.next()) { 200 if (line instanceof MailboxLine) { 201 MailboxEntry entry = ((MailboxLine)line).getMailboxEntry(); 202 if (entry.isNew()) 203 ++newMessageCount; 204 if (entry.isUnread()) 205 ++unreadMessageCount; 206 } 207 } 208 } 209 210 protected boolean clearRecent() 213 { 214 if (!isLocked()) 215 Debug.bug("clearRecent mailbox not locked!"); 216 boolean changed = false; 217 if (entries != null) { 218 final int size = entries.size(); 219 for (int i = 0; i < size; i++) { 220 MailboxEntry entry = (MailboxEntry) entries.get(i); 221 if ((entry.getFlags() & MailboxEntry.RECENT) != 0) { 222 entry.setFlags(entry.getFlags() & ~MailboxEntry.RECENT); 223 changed = true; 224 } 225 } 226 } 227 if (changed) 228 setDirty(true); 229 return changed; 230 } 231 232 public final void setDirty(boolean b) 233 { 234 dirty = b; 235 } 236 237 public final boolean isDirty() 238 { 239 return dirty; 240 } 241 242 public void tag(Editor editor, Line line) 243 { 244 if (line instanceof MailboxLine) { 245 MailboxEntry entry = ((MailboxLine)line).getMailboxEntry(); 246 entry.toggleTag(); 247 Editor.updateInAllEditors(line); 248 if (line.next() != null) { 249 editor.getDot().setLine(line.next()); 250 editor.setMark(null); 251 editor.moveDotToCaretCol(); 252 } 253 } 254 } 255 256 public void tagPattern() 257 { 258 Editor editor = Editor.currentEditor(); 259 InputDialog d = new InputDialog(editor, "Pattern:", "Tag Pattern", null); 260 d.setHistory(new History("mailboxTagPattern")); 261 editor.centerDialog(d); 262 d.show(); 263 String pattern = d.getInput(); 264 if (pattern == null) 265 return; 266 pattern = pattern.trim(); 267 if (pattern.length() == 0) 268 return; 269 editor.repaintNow(); 270 MailboxFilter filter = MailboxFilter.getMailboxFilter(pattern); 271 if (filter != null) 272 tag(filter); 273 else 274 MessageDialog.showMessageDialog("Bad pattern", "Tag Pattern"); 275 } 276 277 private void tag(MailboxFilter filter) 278 { 279 Editor.currentEditor().setWaitCursor(); 280 for (Line line = getFirstLine(); line != null; line = line.next()) { 281 if (line instanceof MailboxLine) { 282 MailboxEntry entry = ((MailboxLine)line).getMailboxEntry(); 283 if (!entry.isTagged()) { 284 if (filter.accept(entry)) { 285 entry.tag(); 286 Editor.updateInAllEditors(line); 287 } 288 } 289 } 290 } 291 } 292 293 public void untagAll() 294 { 295 Editor.currentEditor().setWaitCursor(); 296 for (Line line = getFirstLine(); line != null; line = line.next()) { 297 if (line instanceof MailboxLine) { 298 MailboxEntry entry = ((MailboxLine)line).getMailboxEntry(); 299 if (entry.isTagged()) { 300 entry.untag(); 301 Editor.updateInAllEditors(line); 302 } 303 } 304 } 305 } 306 307 public void toggleRaw() 308 { 309 showRawText = !showRawText; 310 Editor.currentEditor().status("Raw mode " + (showRawText ? "on" : "off")); 311 } 312 313 public List getEntries() 314 { 315 return entries; 316 } 317 318 public List getTaggedEntries() 319 { 320 ArrayList taggedEntries = null; 321 final int size = entries.size(); 322 for (int i = 0; i < size; i++) { 323 MailboxEntry entry = (MailboxEntry) entries.get(i); 324 if (entry.isTagged()) { 325 if (taggedEntries == null) 326 taggedEntries = new ArrayList (); 327 taggedEntries.add(entry); 328 } 329 } 330 return taggedEntries; 331 } 332 333 public MailboxEntry getEntryAtDot(Editor editor) 334 { 335 Line line = editor.getDotLine(); 336 if (line instanceof MailboxLine) 337 return ((MailboxLine)line).getMailboxEntry(); 338 else 339 return null; 340 } 341 342 public abstract void expunge(); 343 344 public abstract int getMessageCount(); 345 346 public Message getMessage(MailboxEntry entry, ProgressNotifier progressNotifier) 347 { 348 Debug.assertTrue(false); 349 return null; 350 } 351 352 public MailboxEntry getNextUndeleted(MailboxEntry entry) 353 { 354 Line line; 355 for (line = getFirstLine(); line != null; line = line.next()) { 356 if (line instanceof MailboxLine) { 357 if (entry == ((MailboxLine)line).getMailboxEntry()) 358 break; 359 } 360 } 361 if (line != null) { 362 for (line = line.next(); line != null; line = line.next()) { 363 if (line instanceof MailboxLine) { 364 MailboxEntry maybe = ((MailboxLine)line).getMailboxEntry(); 365 if (!maybe.isDeleted()) 366 return maybe; 367 } 368 } 369 } 370 return null; 371 } 372 373 public MailboxEntry getPreviousUndeleted(MailboxEntry entry) 374 { 375 Line line; 376 for (line = getFirstLine(); line != null; line = line.next()) { 377 if (line instanceof MailboxLine) { 378 if (entry == ((MailboxLine)line).getMailboxEntry()) 379 break; 380 } 381 } 382 if (line != null) { 383 for (line = line.previous(); line != null; line = line.previous()) { 384 if (line instanceof MailboxLine) { 385 MailboxEntry maybe = ((MailboxLine)line).getMailboxEntry(); 386 if (!maybe.isDeleted()) 387 return maybe; 388 } 389 } 390 } 391 return null; 392 } 393 394 public MailboxEntry getNextInThread(MailboxEntry entry) 395 { 396 String subject = entry.getSubject(); 397 if (subject == null) 398 return null; if (subject.toLowerCase().startsWith("re: ")) 400 subject = subject.substring(4); 401 Line line; 403 for (line = getFirstLine(); line != null; line = line.next()) { 404 if (line instanceof MailboxLine) 405 if (entry == ((MailboxLine)line).getMailboxEntry()) 406 break; 407 } 408 if (line != null) { 409 for (line = line.next(); line != null; line = line.next()) { 411 if (line instanceof MailboxLine) { 412 MailboxEntry maybe = ((MailboxLine)line).getMailboxEntry(); 413 String s = maybe.getSubject(); 415 if (s != null) { 416 if (s.toLowerCase().startsWith("re: ")) 417 s = s.substring(4); 418 if (s.equals(subject)) 419 return maybe; 420 } 421 } 422 } 423 } 424 return null; 425 } 426 427 public MailboxEntry getPreviousInThread(MailboxEntry entry) 428 { 429 String subject = entry.getSubject(); 430 if (subject == null) 431 return null; if (subject.toLowerCase().startsWith("re: ")) 433 subject = subject.substring(4); 434 Line line; 436 for (line = getFirstLine(); line != null; line = line.next()) { 437 if (line instanceof MailboxLine) 438 if (entry == ((MailboxLine)line).getMailboxEntry()) 439 break; 440 } 441 if (line != null) { 442 for (line = line.previous(); line != null; line = line.previous()) { 444 if (line instanceof MailboxLine) { 445 MailboxEntry maybe = ((MailboxLine)line).getMailboxEntry(); 446 String s = maybe.getSubject(); 448 if (s != null) { 449 if (s.toLowerCase().startsWith("re: ")) 450 s = s.substring(4); 451 if (s.equals(subject)) 452 return maybe; 453 } 454 } 455 } 456 } 457 return null; 458 } 459 460 public MailboxEntry getEntryForMessageId(String messageId) 461 { 462 if (messageId == null) 463 return null; 464 if (entries != null) { 465 for (int i = entries.size()-1; i >= 0; i--) { 466 MailboxEntry entry = (MailboxEntry) entries.get(i); 467 if (entry != null) { 468 if (messageId.equals(entry.getMessageId())) 469 return entry; 470 } 471 } 472 } 473 return null; 474 } 475 476 public void bounce() 477 { 478 Debug.assertTrue(SwingUtilities.isEventDispatchThread()); 479 final Editor editor = Editor.currentEditor(); 480 List list = getTaggedEntries(); 481 if (list == null) { 482 MailboxEntry entry = getEntryAtDot(editor); 483 if (entry == null) 484 return; 485 list = new ArrayList (1); 486 list.add(entry); 487 } 488 final List toBeBounced = list; 489 final MailAddress[] to = MailCommands.bounceGetTo(editor, toBeBounced.size()); 491 if (to == null) 492 return; 493 Runnable bounceRunnable = new Runnable () { 494 public void run() 495 { 496 boolean succeeded = false; 497 try { 498 succeeded = bounceMessages(toBeBounced, to); 499 } 500 finally { 501 unlock(); 502 setBusy(false); 503 editor.updateDisplayLater(); 504 } 505 if (succeeded) { 506 Runnable successRunnable = new Runnable () { 507 public void run() 508 { 509 final int size = toBeBounced.size(); 510 FastStringBuffer sb = new FastStringBuffer(String.valueOf(size)); 511 sb.append(" message"); 512 if (size > 1) 513 sb.append('s'); 514 sb.append(" bounced"); 515 editor.status(sb.toString()); 516 } 517 }; 518 SwingUtilities.invokeLater(successRunnable); 519 } else { 520 Runnable errorRunnable = new Runnable () { 521 public void run() 522 { 523 MessageDialog.showMessageDialog(editor, "Failed", "Bounce"); 524 } 525 }; 526 SwingUtilities.invokeLater(errorRunnable); 527 } 528 } 529 }; 530 if (lock()) { 531 setBusy(true); 532 new Thread (bounceRunnable).start(); 533 } else 534 editor.status("Mailbox is locked"); 535 } 536 537 private boolean bounceMessages(List toBeBounced, MailAddress[] to) 538 { 539 Log.debug("bounceMessages initializing SMTP session..."); 540 SmtpSession smtp = SmtpSession.getDefaultSession(); 541 if (smtp == null) 542 return false; 543 try { 544 for (int i = 0; i < toBeBounced.size(); i++) { 545 MailboxEntry entry = (MailboxEntry) toBeBounced.get(i); 546 if (!Mail.bounceMessage(getMessage(entry, null), to, smtp)) 547 return false; 548 } 549 return true; 550 } 551 finally { 552 Debug.assertTrue(smtp != null); 553 Log.debug("bounceMessages closing SMTP session..."); 554 smtp.quit(); 555 } 556 } 557 558 private String limitPattern; 559 560 public final String getLimitPattern() 561 { 562 return limitPattern; 563 } 564 565 public final void setLimitPattern(String pattern) 566 { 567 limitPattern = pattern; 568 } 569 570 public void limit() 571 { 572 Editor editor = Editor.currentEditor(); 573 InputDialog d = new InputDialog(editor, "Pattern:", "Limit", limitPattern); 574 d.setHistory(new History("mailboxLimit")); 575 editor.centerDialog(d); 576 d.show(); 577 String pattern = d.getInput(); 578 if (pattern == null) 579 return; editor.repaintNow(); 581 pattern = pattern.trim(); 582 if (pattern.length() == 0) 583 unlimit(); 584 else { 585 MailboxFilter filter = MailboxFilter.getMailboxFilter(pattern); 586 if (filter != null) { 587 if (lock()) { 588 try { 589 limitPattern = pattern; 590 limit(filter); 591 } 592 finally { 593 unlock(); 594 } 595 } else 596 editor.status("Mailbox is locked"); 597 } else 598 MessageDialog.showMessageDialog("Bad limit pattern", "Limit"); 599 } 600 } 601 602 public void unlimit() 603 { 604 if (lock()) { 605 try { 606 limitPattern = null; 607 limit(null); 608 } 609 finally { 610 unlock(); 611 } 612 } else 613 Editor.currentEditor().status("Mailbox is locked"); 614 } 615 616 private MailboxFilter limitFilter; 618 619 public final MailboxFilter getLimitFilter() 620 { 621 return limitFilter; 622 } 623 624 public final void setLimitFilter(MailboxFilter filter) 625 { 626 limitFilter = filter; 627 } 628 629 public void limit(MailboxFilter filter) 630 { 631 Debug.assertTrue(SwingUtilities.isEventDispatchThread()); 632 final Editor editor = Editor.currentEditor(); 633 editor.repaintNow(); 634 editor.setWaitCursor(); 635 MailboxEntry currentEntry = null; 637 if (editor.getDot() != null && editor.getDotLine() instanceof MailboxLine) 638 currentEntry = ((MailboxLine)editor.getDotLine()).getMailboxEntry(); 639 limitFilter = filter; 640 refreshBuffer(); 641 Sidebar.repaintBufferListInAllFrames(); 643 Line dotLine = null; 644 if (getFirstLine() != null) { 645 dotLine = getFirstLine(); 646 if (currentEntry != null) { 647 boolean groupByThread = 648 getBooleanProperty(Property.GROUP_BY_THREAD); 649 for (Line line = getFirstLine(); line != null; line = line.next()) { 650 MailboxEntry entry = ((MailboxLine)line).getMailboxEntry(); 651 if (entry == currentEntry) { 652 dotLine = line; 653 break; 654 } 655 if (!groupByThread) { 656 if (RFC822Date.compare(entry.getDate(), currentEntry.getDate()) < 0) 657 dotLine = line; 658 else 659 break; 660 } 661 } 662 } 663 } 664 invalidate(); 665 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 666 Editor ed = it.nextEditor(); 667 if (ed.getBuffer() == this) { 668 ed.updateLocation(); 669 Display display = ed.getDisplay(); 670 if (dotLine != null) { 671 ed.setDot(dotLine, 0); 672 display.moveCaretToDotCol(); 673 ed.setMark(null); 674 display.setTopLine(getFirstLine()); 675 display.setUpdateFlag(REPAINT); 676 } else { 677 ed.setDot(null); 678 ed.setMark(null); 679 display.setTopLine(null); 680 } 681 ed.updateDisplay(); 682 } 683 } 684 editor.setDefaultCursor(); 685 } 686 687 public MailboxLine getLineForEntry(MailboxEntry entry) 688 { 689 if (entry != null) { 690 for (Line line = getFirstLine(); line != null; line = line.next()) { 691 if (line instanceof MailboxLine) 692 if (((MailboxLine)line).getMailboxEntry() == entry) 693 return (MailboxLine)line; 694 } 695 } 696 return null; 697 } 698 699 public MailboxLine findLineForEntry(MailboxEntry entry) 700 { 701 if (entry != null) { 702 for (Line l = getFirstLine(); l != null; l = l.next()) { 704 MailboxLine line = (MailboxLine) l; 705 MailboxEntry e = line.getMailboxEntry(); 706 if (e == entry) 707 return line; 708 } 709 boolean groupByThread = 711 getBooleanProperty(Property.GROUP_BY_THREAD); 712 for (Line l = getFirstLine(); l != null; l = l.next()) { 713 if (l instanceof MailboxLine) { 714 MailboxLine line = (MailboxLine) l; 715 MailboxEntry e = line.getMailboxEntry(); 716 if (e.getDate().equals(entry.getDate())) { 718 if (e.getSize() == entry.getSize()) { 719 Log.debug("findLineForEntry date/size match"); 721 return line; 722 } 723 } else if (!groupByThread) { 724 if (RFC822Date.compare(e.getDate(), entry.getDate()) > 0) { 725 return line; 729 } 730 } else if (line.next() == null) { 731 return line; 733 } 734 } 735 } 736 } 737 return null; 738 } 739 740 public int getLineNumberForEntry(MailboxEntry entry) 741 { 742 Line line = getLineForEntry(entry); 743 if (line != null) 744 return line.lineNumber(); 745 else 746 return -1; 747 } 748 749 public Position getInitialDotPos() 751 { 752 if (getFirstLine() == null) 753 return null; 754 Line line = getFirstLine(); 755 while (true) { 756 if (line instanceof MailboxLine) { 757 MailboxEntry entry = ((MailboxLine)line).getMailboxEntry(); 758 if (entry != null) { 759 int flags = entry.getFlags(); 760 if ((flags & MailboxEntry.SEEN) == 0) 761 if ((flags & MailboxEntry.DELETED) == 0) 762 return new Position(line, 0); 763 } 764 } 765 if (line.next() == null) 766 break; line = line.next(); 768 } 769 return new Position(line, 0); 770 } 771 772 public MailboxEntry getInitialEntry() 773 { 774 if (getFirstLine() == null) 775 return null; 776 Line line = getFirstLine(); 777 while (true) { 778 if (line instanceof MailboxLine) { 779 MailboxEntry entry = ((MailboxLine)line).getMailboxEntry(); 780 if (entry != null) { 781 int flags = entry.getFlags(); 782 if ((flags & MailboxEntry.SEEN) == 0) 783 if ((flags & MailboxEntry.DELETED) == 0) 784 return entry; 785 } 786 } 787 if (line.next() == null) 788 break; line = line.next(); 790 } 791 return ((MailboxLine)line).getMailboxEntry(); 792 } 793 794 public void updateEntry(MailboxEntry entry) 795 { 796 MailboxLine line = getLineForEntry(entry); 797 if (line != null) { 798 line.setText(entry.toString(line.getDepth())); 799 Editor.updateInAllEditors(this, line); 800 } 801 } 802 803 public final void toggleGroupByThread() 804 { 805 boolean groupByThread = getBooleanProperty(Property.GROUP_BY_THREAD); 806 setProperty(Property.GROUP_BY_THREAD, !groupByThread); 807 sort(); 808 } 809 810 private void sort() 811 { 812 final Editor editor = Editor.currentEditor(); 813 final MailboxEntry currentEntry; 815 if (editor.getDot() != null && editor.getDotLine() instanceof MailboxLine) 816 currentEntry = ((MailboxLine)editor.getDotLine()).getMailboxEntry(); 817 else 818 currentEntry = null; 819 final Runnable completionRunnable = new Runnable () { 820 public void run() 821 { 822 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 823 Editor ed = it.nextEditor(); 824 View view = new View(); 825 view.setDotEntry(currentEntry != null ? currentEntry : getInitialEntry()); 826 ed.setView(Mailbox.this, view); 827 if (ed.getBuffer() == Mailbox.this) { 828 ed.bufferActivated(true); 829 ed.updateDisplay(); 830 } 831 } 832 } 833 }; 834 Runnable sortRunnable = new Runnable () { 835 public void run() 836 { 837 editor.setWaitCursor(); 838 try { 839 refreshBuffer(); 840 SwingUtilities.invokeLater(completionRunnable); 841 } 842 finally { 843 unlock(); 844 setBusy(false); 845 editor.setDefaultCursor(); 846 } 847 } 848 }; 849 if (lock()) { 850 setBusy(true); 851 new Thread (sortRunnable).start(); 852 } 853 } 854 855 public void foldThread(Line line) 856 { 857 if (!getBooleanProperty(Property.GROUP_BY_THREAD)) 858 return; 859 if (line instanceof MailboxLine) { 860 MailboxLine begin = (MailboxLine) line; 861 while (begin.getDepth() > 1) { 863 Line prev = begin.previous(); 864 if (prev instanceof MailboxLine) 865 begin = (MailboxLine) prev; 866 else 867 break; 868 } 869 if (begin.next() instanceof MailboxLine) { 870 MailboxLine end = (MailboxLine) begin.next(); 871 while (end.getDepth() > 1) { 872 Line next = end.next(); 873 if (next instanceof MailboxLine) 874 end = (MailboxLine) next; 875 else 876 break; 877 } 878 for (Line toBeHidden = begin.next(); toBeHidden != end && toBeHidden != null; toBeHidden = toBeHidden.next()) 879 toBeHidden.hide(); 880 renumber(); 881 Editor.unhideDotInAllFrames(this); 882 } 883 } 884 } 885 886 public void foldThreads() 887 { 888 if (!getBooleanProperty(Property.GROUP_BY_THREAD)) 889 return; 890 for (Line line = getFirstLine(); line != null; line = line.nextVisible()) { 891 if (line instanceof MailboxLine) { 892 MailboxLine begin = (MailboxLine) line; 893 if (begin.getDepth() == 1) { 894 if (begin.next() instanceof MailboxLine) { 895 MailboxLine end = (MailboxLine) begin.next(); 896 while (end.getDepth() > 1) { 897 Line next = end.next(); 898 if (next instanceof MailboxLine) 899 end = (MailboxLine) next; 900 else 901 break; 902 } 903 for (Line toBeHidden = begin.next(); toBeHidden != end && toBeHidden != null; toBeHidden = toBeHidden.next()) 904 toBeHidden.hide(); 905 } 906 } 907 } 908 } 909 renumber(); 910 Editor.unhideDotInAllFrames(this); 911 } 912 913 protected void refreshBuffer() 914 { 915 if (getBooleanProperty(Property.GROUP_BY_THREAD)) { 916 long start = System.currentTimeMillis(); 917 SortByThread sort = new SortByThread(entries); 918 sort.run(); 919 try { 920 lockWrite(); 921 } 922 catch (InterruptedException e) { 923 Log.error(e); 924 return; 925 } 926 try { 927 synchronized (this) { 928 empty(); 929 sort.addEntries(this, limitFilter); 930 renumber(); 931 countMessages(); 932 setLoaded(true); 933 } 934 } 935 finally { 936 unlockWrite(); 937 } 938 long elapsed = System.currentTimeMillis() - start; 939 Log.debug("refreshBuffer " + elapsed + " ms"); 940 } else { 941 Debug.assertTrue(sortBy == SORT_BY_DATE_SENT); 942 ArrayList temp = new ArrayList (entries); 944 sortEntriesByDate(temp); 945 List matchingEntries = getMatchingEntries(temp, limitFilter); 946 try { 947 lockWrite(); 948 } 949 catch (InterruptedException e) { 950 Log.error(e); 951 return; 952 } 953 try { 954 synchronized (this) { 955 empty(); 956 final int size = matchingEntries.size(); 957 for (int i = 0; i < size; i++) 958 appendLine(((MailboxEntry)matchingEntries.get(i))); 959 renumber(); 960 countMessages(); 961 setLoaded(true); 962 } 963 } 964 finally { 965 unlockWrite(); 966 } 967 } 968 } 969 970 private static List getMatchingEntries(List list, MailboxFilter filter) 972 { 973 if (list == null) 974 return new ArrayList (); 975 if (filter == null) 976 return new ArrayList (list); 977 ArrayList matchingEntries = new ArrayList (); 978 final int size = list.size(); 979 for (int i = 0; i < size; i++) { 980 MailboxEntry entry = (MailboxEntry) list.get(i); 981 if (filter.accept(entry)) 982 matchingEntries.add(entry); 983 } 984 return matchingEntries; 985 } 986 987 public final void appendLine(MailboxEntry entry) 988 { 989 appendLine(new MailboxLine(entry)); 990 } 991 992 public final void appendLine(MailboxEntry entry, int depth) 993 { 994 appendLine(new MailboxLine(entry, depth)); 995 } 996 997 private static void sortEntriesByDate(List list) 998 { 999 Comparator c = new Comparator () { 1000 public int compare(Object o1, Object o2) 1001 { 1002 return RFC822Date.compare(((MailboxEntry)o1).getDate(), 1003 ((MailboxEntry)o2).getDate()); 1004 } 1005 }; 1006 Collections.sort(list, c); 1007 int sequenceNumber = 1; 1008 Iterator iter = list.iterator(); 1009 while (iter.hasNext()) { 1010 MailboxEntry entry = (MailboxEntry) iter.next(); 1011 entry.setSequenceNumber(sequenceNumber++); 1012 } 1013 } 1014 1015 protected void addEntriesToAddressBook(List list) 1016 { 1017 if (list == null) 1018 return; 1019 MailAddress userMailAddress = Mail.getUserMailAddress(); 1020 AddressBook addressBook = AddressBook.getGlobalAddressBook(); 1021 for (int i = 0; i < list.size(); i++) { 1022 MailboxEntry sourceEntry = (MailboxEntry) list.get(i); 1023 int flags = sourceEntry.getFlags(); 1024 if ((flags & MailboxEntry.DELETED) != 0) 1025 continue; 1026 MailAddress[] from = sourceEntry.getFrom(); 1027 MailAddress[] to = sourceEntry.getTo(); 1028 MailAddress[] cc = sourceEntry.getCc(); 1029 boolean add = false; 1030 if ((flags & MailboxEntry.ANSWERED) != 0) { 1031 add = true; 1033 } else if (from != null) { 1034 for (int j = 0; j < from.length; j++) { 1035 MailAddress a = from[j]; 1036 if (a.matches(userMailAddress)) { 1037 add = true; 1039 break; 1040 } 1041 } 1042 } 1043 if (!add) { 1044 if (to != null) { 1045 for (int j = 0; j < to.length; j++) { 1046 MailAddress a = to[j]; 1047 if (a.matches(userMailAddress)) { 1048 add = true; 1050 break; 1051 } 1052 } 1053 } 1054 if (!add && cc != null) { 1055 for (int j = 0; j < cc.length; j++) { 1056 MailAddress a = cc[j]; 1057 if (a.matches(userMailAddress)) { 1058 add = true; 1060 break; 1061 } 1062 } 1063 } 1064 } 1065 if (add) { 1066 if (to != null) 1067 for (int j = 0; j < to.length; j++) 1068 addressBook.maybeAddMailAddress(to[j]); 1069 if (cc != null) 1070 for (int j = 0; j < cc.length; j++) 1071 addressBook.maybeAddMailAddress(cc[j]); 1072 if (from != null) 1073 for (int j = 0; j < from.length; j++) 1074 addressBook.maybeAddMailAddress(from[j]); 1075 } 1076 } 1077 AddressBook.saveGlobalAddressBook(); 1078 } 1079 1080 public Icon getIcon() 1082 { 1083 return Utilities.getIconFromFile(newMessageCount > 0 ? "mailbox_new.png" : "mailbox.png"); 1084 } 1085 1086 public String getFileNameForDisplay() 1087 { 1088 return ""; 1089 } 1090 1091 protected void newMessagesStatus() 1092 { 1093 if (newMessageCount > 0) { 1094 FastStringBuffer sb = new FastStringBuffer(32); 1095 sb.append(String.valueOf(newMessageCount)); 1096 sb.append(" new message"); 1097 if (newMessageCount > 1) 1098 sb.append('s'); 1099 status(sb.toString()); 1100 } else 1101 status("No new messages"); 1102 } 1103 1104 protected void status(final String s) 1105 { 1106 Runnable r = new Runnable () { 1107 public void run() 1108 { 1109 for (int i = 0; i < Editor.getFrameCount(); i++) { 1110 Editor ed = Editor.getFrame(i).getCurrentEditor(); 1111 if (ed.getBuffer() == Mailbox.this) 1112 ed.status(s); 1113 } 1114 } 1115 }; 1116 SwingUtilities.invokeLater(r); 1117 } 1118 1119 public MailAddress getUserMailAddress() 1120 { 1121 String address = getStringProperty(Property.USER_MAIL_ADDRESS); 1122 if (address == null) 1123 return null; 1124 return new MailAddress(getStringProperty(Property.USER_FULL_NAME), address); 1125 } 1126 1127 public boolean isChildVisible() 1128 { 1129 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1130 Buffer buffer = it.nextEditor().getBuffer(); 1131 if (buffer instanceof MessageBuffer) 1132 if (((MessageBuffer)buffer).getMailbox() == this) 1133 return true; 1134 } 1135 return false; 1136 } 1137 1138 public boolean isIdle(int fg, int bg) 1141 { 1142 if (!isVisible() && !isChildVisible()) { 1143 if (bg == 0) 1145 return false; 1146 else if (System.currentTimeMillis() - Dispatcher.getLastEventMillis() > bg * 1000) 1147 return true; 1148 else 1149 return false; 1150 } else { 1151 if (fg == 0) 1153 return false; 1154 else if (System.currentTimeMillis() - Dispatcher.getLastEventMillis() > fg * 1000) 1155 return true; 1156 else 1157 return false; 1158 } 1159 } 1160 1161 protected void error(final String text, final String title) 1162 { 1163 Runnable r = new Runnable () { 1164 public void run() 1165 { 1166 Editor editor = Editor.currentEditor(); 1167 setBusy(false); 1169 editor.updateDisplay(); 1170 MessageDialog.showMessageDialog(editor, text, title); 1171 } 1172 }; 1173 SwingUtilities.invokeLater(r); 1174 } 1175 1176 protected void success(final String text) 1177 { 1178 Runnable r = new Runnable () { 1179 public void run() 1180 { 1181 Editor.currentEditor().status(text); 1182 } 1183 }; 1184 SwingUtilities.invokeLater(r); 1185 } 1186 1187 protected void saveDisplayState() 1188 { 1189 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1190 Editor ed = it.nextEditor(); 1191 if (ed.getBuffer() == this) 1192 ed.saveView(); 1193 } 1194 } 1195 1196 protected void updateDisplay() 1197 { 1198 SwingUtilities.invokeLater(updateDisplayRunnable); 1199 } 1200 1201 private Runnable updateDisplayRunnable = new Runnable () { 1202 public void run() 1203 { 1204 invalidate(); 1205 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1206 Editor ed = it.nextEditor(); 1207 if (ed.getBuffer() == Mailbox.this) { 1208 View view = ed.getView(ed.getBuffer()); 1209 if (view.getDotEntry() != null) { 1210 try { 1211 lockRead(); 1212 } 1213 catch (InterruptedException e) { 1214 Log.error(e); 1215 return; 1216 } 1217 try { 1218 Line topLine = findLineForEntry(view.getTopEntry()); 1219 if (topLine == null) 1220 topLine = getFirstLine(); 1221 ed.setTopLine(topLine); 1222 Line dotLine = findLineForEntry(view.getDotEntry()); 1223 if (dotLine != null) { 1224 int offset = view.getDotOffset(); 1225 if (offset > dotLine.length()) 1226 offset = dotLine.length(); 1227 ed.setDot(dotLine, offset); 1228 ed.moveCaretToDotCol(); 1229 } else { 1230 dotLine = getLastLine(); 1231 if (dotLine != null) { 1232 Log.debug("updateDisplayRunnable setting dotLine to last line"); 1233 ed.setDot(dotLine, 0); 1234 ed.moveCaretToDotCol(); 1235 } else 1236 ed.setDot(null); 1237 } 1238 ed.setMark(null); 1239 } 1240 finally { 1241 unlockRead(); 1242 } 1243 } else { 1244 Line firstLine = getFirstLine(); 1245 if (firstLine != null) { 1246 ed.setDot(firstLine, 0); 1247 ed.moveCaretToDotCol(); 1248 ed.setMark(null); 1249 ed.setTopLine(firstLine); 1250 } else { 1251 ed.setDot(null); 1252 ed.setMark(null); 1253 ed.setTopLine(null); 1254 } 1255 } 1256 ed.setUpdateFlag(REPAINT); 1257 ed.updateDisplay(); 1258 } 1259 } 1260 Sidebar.setUpdateFlagInAllFrames(SIDEBAR_BUFFER_LIST_CHANGED); 1261 Sidebar.repaintBufferListInAllFrames(); 1262 } 1263 }; 1264 1265 protected void advanceDot(final Line dotLine) 1266 { 1267 final Line nextLine = dotLine.next(); 1268 if (nextLine != null) 1269 setDotLine(nextLine); 1270 } 1271 1272 public void setDotEntry(MailboxEntry entry) 1273 { 1274 final MailboxLine line = findLineForEntry(entry); 1275 if (line != null && line.getMailboxEntry() == entry) 1276 setDotLine(line); 1277 } 1278 1279 private void setDotLine(final Line line) 1280 { 1281 Runnable r = new Runnable () { 1282 public void run() 1283 { 1284 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 1285 Editor ed = it.nextEditor(); 1286 if (ed.getBuffer() == Mailbox.this) { 1287 if (ed.getDot() != null) { 1288 ed.update(ed.getDotLine()); 1289 ed.getDot().moveTo(line, 0); 1290 ed.update(line); 1291 ed.moveCaretToDotCol(); 1292 ed.clearStatusText(); 1293 ed.updateDisplay(); 1294 } 1295 } 1296 } 1297 } 1298 }; 1299 if (SwingUtilities.isEventDispatchThread()) 1300 r.run(); 1301 else 1302 SwingUtilities.invokeLater(r); 1303 } 1304 1305 public String getStatusText(Editor editor) 1306 { 1307 FastStringBuffer sb = new FastStringBuffer(); 1308 if (editor.getDot() != null) { 1309 sb.append("Message "); 1310 sb.append(String.valueOf(editor.getDotLineNumber()+1)); 1311 sb.append(" of "); 1312 sb.append(String.valueOf(getLineCount())); 1313 final int u = getUnreadMessageCount(); 1314 if (u > 0) { 1315 final int n = getNewMessageCount(); 1316 sb.append(" ("); 1317 if (n > 0) { 1318 sb.append(n); 1319 sb.append(" new, "); 1320 } 1321 sb.append(u); 1322 sb.append(" unread)"); 1323 } 1324 } else { 1325 sb.append("No messages"); 1326 } 1327 return sb.toString(); 1328 } 1329 1330 public void saveView(Editor editor) 1331 { 1332 final View view = saveViewInternal(editor); 1333 final Line topLine = editor.getTopLine(); 1334 if (topLine instanceof MailboxLine) 1335 view.setTopEntry(((MailboxLine)topLine).getMailboxEntry()); 1336 if (editor.getDot() != null) { 1337 Line dotLine = editor.getDotLine(); 1338 if (dotLine instanceof MailboxLine) 1339 view.setDotEntry(((MailboxLine)dotLine).getMailboxEntry()); 1340 } 1341 editor.setView(this, view); 1342 setLastView(view); 1343 } 1344 1345 public void restoreView(Editor editor) 1346 { 1347 final Display display = editor.getDisplay(); 1348 final View view = editor.getView(this); 1349 Debug.assertTrue(view != null); 1350 if (view != null) { 1351 if (view.getDotEntry() == null) { 1352 super.restoreView(editor); 1353 return; 1354 } 1355 Line topLine = findLineForEntry(view.getTopEntry()); 1356 if (topLine == null) 1357 topLine = getFirstLine(); 1358 display.setTopLine(topLine); 1359 Line dotLine = findLineForEntry(view.getDotEntry()); 1360 if (dotLine == null) 1361 dotLine = getFirstLine(); 1362 if (view.getTopLine() == topLine && view.getDot() != null && view.getDot().getLine() == dotLine) { 1363 editor.setDot(new Position(view.getDot())); 1364 editor.setMark(view.getMark() == null ? null : new Position(view.getMark())); 1365 editor.setSelection(view.getSelection()); 1366 display.setTopLine(view.getTopLine()); 1367 display.setShift(view.getShift()); 1368 display.setCaretCol(view.getCaretCol()); 1369 } else { 1370 editor.setDot(dotLine != null ? new Position(dotLine, 0) : null); 1371 editor.moveCaretToDotCol(); 1372 editor.setMark(null); 1373 } 1374 } 1375 } 1376 1377 protected void notImplemented(String s) 1378 { 1379 Log.error(s.concat(" is not implemented")); 1380 } 1381} 1382 | Popular Tags |