1 21 22 package org.armedbear.j.mail; 23 24 import java.io.BufferedReader ; 25 import java.io.BufferedWriter ; 26 import java.io.FileNotFoundException ; 27 import java.io.FileReader ; 28 import java.io.FileWriter ; 29 import java.io.IOException ; 30 import java.io.InputStream ; 31 import java.io.OutputStream ; 32 import java.io.RandomAccessFile ; 33 import java.text.SimpleDateFormat ; 34 import java.util.ArrayList ; 35 import java.util.Calendar ; 36 import java.util.HashSet ; 37 import java.util.Iterator ; 38 import java.util.List ; 39 import java.util.Locale ; 40 import java.util.Properties ; 41 import javax.swing.SwingUtilities ; 42 import org.armedbear.j.BackgroundProcess; 43 import org.armedbear.j.Debug; 44 import org.armedbear.j.Editor; 45 import org.armedbear.j.Directories; 46 import org.armedbear.j.EditorIterator; 47 import org.armedbear.j.File; 48 import org.armedbear.j.FastStringBuffer; 49 import org.armedbear.j.Log; 50 import org.armedbear.j.PasswordDialog; 51 import org.armedbear.j.Property; 52 import org.armedbear.j.StatusBarProgressNotifier; 53 import org.armedbear.j.Utilities; 54 import org.armedbear.j.View; 55 56 public final class PopMailbox extends LocalMailbox 57 { 58 private final PopSession session; 59 60 private File localStore; 61 private StatusBarProgressNotifier progressNotifier; 62 private boolean cancelled; 63 private Thread backgroundThread; 64 65 public PopMailbox(PopURL url, PopSession session) 66 { 67 super(url); 68 this.session = session; 69 if (url.getUser() == null) 70 url.setUser(session.getUser()); 71 setMailboxFile(getLocalStore()); 72 setInitialized(true); 73 } 74 75 public String getFileNameForDisplay() 76 { 77 FastStringBuffer sb = new FastStringBuffer(64); 78 sb.append(url.toString()); 79 String limitPattern = getLimitPattern(); 80 if (limitPattern != null) { 81 sb.append(' '); 82 sb.append(limitPattern); 83 } 84 return sb.toString(); 85 } 86 87 public final String getName() 88 { 89 return url.toString(); 90 } 91 92 public synchronized int load() 93 { 94 if (isLoaded()) 95 return LOAD_COMPLETED; 96 if (lock()) { 97 Debug.assertTrue(backgroundThread == null); 98 backgroundThread = new Thread (loadProcess); 99 backgroundThread.start(); 100 setLoaded(true); 101 return LOAD_PENDING; 102 } 103 Debug.bug("PopMailbox.load can't lock mailbox"); 105 return LOAD_FAILED; 106 } 107 108 private BackgroundProcess loadProcess = new BackgroundProcess() { 109 public void run() 110 { 111 boolean abort = false; 113 try { 114 setBusy(true); 115 cancelled = false; 116 progressNotifier = new StatusBarProgressNotifier(PopMailbox.this); 117 progressNotifier.progressStart(); 118 setBackgroundProcess(this); 119 readMailboxFile(progressNotifier); if (cancelled) { 121 abort = true; 122 return; 123 } 124 readExpungedUidlsList(); 125 clearRecent(); 126 if (cancelled || getBooleanProperty(Property.OFFLINE)) 127 return; 128 if (retrieveNewMessages()) { 129 addEntriesToAddressBook(entries); 130 setLastCheckMillis(System.currentTimeMillis()); 131 } else if (!cancelled) { 132 error(session.getErrorText(), url.toString()); 134 } 135 } 136 finally { 137 if (abort) { 138 Runnable r = new Runnable () { 139 public void run() 140 { 141 kill(); 142 for (EditorIterator it = new EditorIterator(); it.hasNext();) 143 it.nextEditor().updateDisplay(); 144 } 145 }; 146 SwingUtilities.invokeLater(r); 147 } else { 148 refreshBuffer(); 149 Runnable r = new Runnable () { 150 public void run() 151 { 152 setBusy(false); 153 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 154 Editor ed = it.nextEditor(); 155 View view = new View(); 156 view.setDotEntry(getInitialEntry()); 157 ed.setView(PopMailbox.this, view); 158 if (ed.getBuffer() == PopMailbox.this) { 159 ed.bufferActivated(true); 160 ed.updateDisplay(); 161 } 162 } 163 } 164 }; 165 SwingUtilities.invokeLater(r); 166 } 167 setBackgroundProcess(null); 168 backgroundThread = null; 169 if (progressNotifier != null) { 170 progressNotifier.setText(cancelled ? "Cancelled" : ""); 171 progressNotifier.progressStop(); 172 progressNotifier = null; 173 } 174 unlock(); 175 } 176 } 177 178 public void cancel() 179 { 180 Log.debug("loadProcess.cancel"); 181 cancelled = true; 182 progressNotifier.cancel(); 183 progressNotifier.setText("Cancelled, cleaning up..."); 184 if (backgroundThread != null && backgroundThread.isAlive()) 185 backgroundThread.interrupt(); 186 session.disconnect(); 187 } 188 }; 189 190 public void getNewMessages() 191 { 192 if (session.getPassword() == null) { 193 String password = 194 PasswordDialog.showPasswordDialog(Editor.currentEditor(), 195 "Password:", "Password"); 196 if (password == null || password.length() == 0) 197 return; 198 session.setPassword(password); 199 } 200 if (lock()) 201 getNewMessages(true); 202 else 203 Editor.currentEditor().status("Mailbox is locked"); 204 } 205 206 public void getNewMessages(boolean userInitiated) 207 { 208 Debug.assertTrue(isLocked()); 209 if (session.getPassword() == null) 212 return; 213 Log.debug("PopMailbox.getNewMessages " + userInitiated); 214 setBusy(true); 215 Log.debug("PopMailbox.getNewMessages back from setBusy(true)"); 216 if (userInitiated) 217 saveDisplayState(); 218 Debug.assertTrue(backgroundThread == null); 219 backgroundThread = new Thread (new GetNewMessagesProcess(userInitiated)); 220 backgroundThread.start(); 221 } 222 223 private class GetNewMessagesProcess implements BackgroundProcess 224 { 225 private boolean userInitiated; 226 227 GetNewMessagesProcess(boolean userInitiated) 229 { 230 this.userInitiated = userInitiated; 231 } 232 233 public void run() 234 { 235 try { 236 boolean changed = false; 237 if (userInitiated) 238 changed = clearRecent(); 239 cancelled = false; 240 progressNotifier = new StatusBarProgressNotifier(PopMailbox.this); 241 progressNotifier.progressStart(); 242 setBackgroundProcess(this); 243 int oldSize = entries.size(); 244 boolean ok = retrieveNewMessages(); 245 if (changed || entries.size() != oldSize) { 246 refreshBuffer(); 247 addEntriesToAddressBook(entries); 248 updateDisplay(); 249 } 250 newMessagesStatus(); 251 if (!ok) { 252 if (userInitiated && !cancelled) 253 error(session.getErrorText(), url.toString()); 254 } 255 } 256 finally { 257 setBusy(false); 258 if (progressNotifier != null) { 259 progressNotifier.setText(cancelled ? "Cancelled" : ""); 260 progressNotifier.progressStop(); 261 progressNotifier = null; 262 } 263 setBackgroundProcess(null); 264 backgroundThread = null; 265 setLastCheckMillis(System.currentTimeMillis()); 266 unlock(); 267 Editor.updateDisplayLater(PopMailbox.this); 268 } 269 } 270 271 public void cancel() 272 { 273 Log.debug("GetNewMessagesProcess.cancel"); 274 cancelled = true; 275 progressNotifier.cancel(); 276 progressNotifier.setText("Cancelled, cleaning up..."); 277 if (backgroundThread != null && backgroundThread.isAlive()) { 278 Log.debug("interrupting background thread..."); 279 backgroundThread.interrupt(); 280 } 281 session.disconnect(); 282 } 283 } 284 285 private boolean retrieveNewMessages() 286 { 287 Log.debug("PopMailbox.retrieveNewMessages"); 288 if (!connect()) 289 return false; 290 File outputFile = null; 291 long start = System.currentTimeMillis(); 292 try { 293 if (Thread.currentThread().isInterrupted() || cancelled) 294 return true; 295 int count = stat(); 296 if (count < 0) 297 return false; if (count == 0) 299 return true; if (Thread.currentThread().isInterrupted() || cancelled) 301 return true; 302 List serverMessageList = getServerMessageList(count); 303 if (serverMessageList == null) 304 return false; if (Thread.currentThread().isInterrupted() || cancelled) 306 return true; 307 pruneExpungedUidlsList(serverMessageList); 310 if (Thread.currentThread().isInterrupted() || cancelled) 311 return true; 312 List messagesToBeRetrieved = 315 getMessagesToBeRetrieved(serverMessageList); 316 if (Thread.currentThread().isInterrupted() || cancelled) 317 return true; 318 if (messagesToBeRetrieved.size() == 0) { 320 if (!getBooleanProperty(Property.POP_KEEP_MESSAGES_ON_SERVER)) 323 deleteMessagesOnServer(serverMessageList); 324 Log.debug("no new messages"); 325 return true; 326 } 327 if (getLocalStore() == null) 328 return false; if (localStore.isFile() && localStore.length() > 0) { 330 outputFile = Utilities.getTempFile(localStore.getParentFile()); 331 Log.debug("calling copyFile"); 332 long copyStart = System.currentTimeMillis(); 333 if (!Utilities.copyFile(localStore, outputFile)) 334 return false; 335 Log.debug("back from copyFile " + (System.currentTimeMillis() - copyStart) + " ms"); 336 } else 337 outputFile = localStore; 338 MailboxFileWriter writer = 339 MailboxFileWriter.getInstance(outputFile, true); if (writer == null) 341 return false; boolean ok = retrieveMessages(messagesToBeRetrieved, writer); 343 try { 344 writer.flush(); 345 writer.close(); 346 } 347 catch (IOException e) { 348 Log.error(e); 349 return false; 350 } 351 if (!ok) { 352 Log.debug("not ok..."); 353 if (entries.size() == 0) 356 return false; 357 LocalMailboxEntry entry = 358 (LocalMailboxEntry) entries.get(entries.size() - 1); 359 long offset = entry.getNextMessageStart(); try { 361 RandomAccessFile raf = 362 outputFile.getRandomAccessFile("rw"); 363 Log.debug("before raf.length() = " + raf.length()); 364 Log.debug("truncating to " + offset); 365 raf.setLength(offset); 366 Log.debug("after raf.length() = " + raf.length()); 367 raf.close(); 368 } 369 catch (IOException e) { 370 Log.error(e); 371 return false; 372 } 373 } 374 if (outputFile != localStore) 375 if (!Utilities.deleteRename(outputFile, localStore)) 376 return false; 377 if (getBooleanProperty(Property.POP_KEEP_MESSAGES_ON_SERVER) == false) 378 deleteMessagesOnServer(serverMessageList); 379 outputFile = null; 380 } 381 finally { 382 Log.debug("retrieveNewMessages calling logout() ..."); 383 session.logout(); 384 if (outputFile != null && outputFile.isFile()) 385 outputFile.delete(); 386 } 387 Log.debug("retrieveNewMessages " + (System.currentTimeMillis() - start) + " ms"); 388 return true; } 390 391 private boolean connect() 392 { 393 if (progressNotifier != null) 394 progressNotifier.setText("Connecting to " + session.getHost()); 395 if (session.connect()) { 396 if (progressNotifier != null) 397 progressNotifier.setText("Connected to " + session.getHost()); 398 return true; 399 } 400 return false; 401 } 402 403 private int stat() 405 { 406 int count = -1; 407 session.write("stat"); 408 String response = session.readLine(); 409 if (response.startsWith("+OK")) { 410 try { 411 count = Utilities.parseInt(response.substring(3).trim()); 412 } 413 catch (NumberFormatException e) { 414 Log.error(e); 415 } 416 } else { 417 Log.error("stat failed"); 418 Log.error(response); 419 } 420 return count; 421 } 422 423 private List getServerMessageList(int count) 424 { 425 long start = System.currentTimeMillis(); 426 session.write("uidl"); 427 String response = session.readLine(); 428 if (!response.startsWith("+OK")) { 429 Log.error("getServerMessageList uidl failed"); 430 Log.error(response); 431 return null; 432 } 433 List list = new ArrayList (count); 434 while (true) { 435 String s = session.readLine(); 436 if (s == null) 437 return null; if (s.equals(".")) 439 break; 440 int index = s.indexOf(' '); 441 if (index >= 0) { 442 int messageNumber = Integer.parseInt(s.substring(0, index)); String uidl = s.substring(index + 1); 444 if (messageNumber >= 1) 445 list.add(new MessageListEntry(messageNumber, uidl)); 446 } 447 } 448 Log.debug("getServerMessageList " + (System.currentTimeMillis() - start) + " ms"); 449 Log.debug("getServerMessageList count = " + count + " list size = " + list.size()); 450 return list; 451 } 452 453 private List getMessagesToBeRetrieved(List serverMessageList) 454 { 455 long start = System.currentTimeMillis(); 456 HashSet hashSet = null; 457 if (entries != null) { 458 int size = entries.size(); 459 hashSet = new HashSet (size); 460 for (int i = 0; i < size; i++) { 461 LocalMailboxEntry mailboxEntry = 462 (LocalMailboxEntry) entries.get(i); 463 hashSet.add(mailboxEntry.getUidl()); 464 } 465 } 466 List toBeReturned = new ArrayList (); 467 int size = serverMessageList.size(); 468 for (int i = 0; i < size; i++) { 469 MessageListEntry messageListEntry = 470 (MessageListEntry) serverMessageList.get(i); 471 String uidl = messageListEntry.uidl; 472 if (isExpunged(uidl)) 473 continue; 474 if (hashSet != null && hashSet.contains(uidl)) 475 continue; 476 toBeReturned.add(messageListEntry); 477 } 478 Log.debug("getMessagesToBeRetrieved " + (System.currentTimeMillis() - start) + " ms"); 479 return toBeReturned; 480 } 481 482 private boolean retrieveMessages(List messageList, MailboxFileWriter writer) 483 { 484 Log.debug("entering retrieveMessages"); 485 long start = System.currentTimeMillis(); 486 for (int i = 0; i < messageList.size(); i++) { 487 String text = "Retrieving message " + (i + 1) + " of " + messageList.size(); 488 if (i == 0) 489 progressNotifier.setText(text); else 491 progressNotifier.progress(text); 492 MessageListEntry entry = (MessageListEntry) messageList.get(i); 493 if (!retrieveMessage(entry.messageNumber, entry.uidl, writer)) { 494 Log.error("retrieveMessages error retrieving message " + entry.messageNumber); 495 return false; 496 } 497 } 498 progressNotifier.setText(cancelled ? "Cancelled, cleaning up" : ""); 499 Log.debug("leaving retrieveMessages " +(System.currentTimeMillis() - start) + " ms"); 500 return true; 501 } 502 503 private boolean retrieveMessage(int i, String uidl, MailboxFileWriter writer) 505 { 506 String command = "list " + i; 507 session.write(command); 508 int size = 0; 509 String response = session.readLine(); 510 String expected = "+OK " + i + " "; 511 if (response != null && response.startsWith(expected)) { 512 try { 513 size = Integer.parseInt(response.substring(expected.length())); 514 } 515 catch (NumberFormatException e) { 516 Log.error(e); 517 return false; } 519 } else { 520 Log.error("retrieveMessage command failed: " + command); 521 Log.error("response = " + response); 522 } 523 command = "retr " + i; 524 session.write(command); 525 response = session.readLine(); 526 if (response == null || !response.startsWith("+OK")) { 527 Log.error("retrieveMessage command failed: " + command); 528 Log.error(response); 529 return false; } 531 try { 532 final long messageStart = writer.getOffset(); 533 writer.write("From - "); 534 writer.write(getDateTimeStamp()); 535 writer.write('\n'); 536 FastStringBuffer sb = new FastStringBuffer(2048); 538 while (true) { 539 String s = session.readLine(); 540 if (s == null) 541 return false; if (s.length() == 0) { 543 String status = "X-J-Status: 0\n"; 546 writer.write(status); 547 sb.append(status); 548 if (uidl != null) { 550 writer.write("X-UIDL: "); 551 writer.write(uidl); 552 writer.write('\n'); 553 sb.append("X-UIDL: "); 554 sb.append(uidl); 555 sb.append('\n'); 556 } 557 writer.write('\n'); 558 break; 559 } 560 if (s.toUpperCase().startsWith("X-UIDL")) 561 continue; 562 writer.write(s); 563 writer.write('\n'); 564 sb.append(s); 565 sb.append('\n'); 566 } 567 boolean echo = session.getEcho(); 569 session.setEcho(false); 570 while (true) { 571 String s = session.readLine(); 572 if (s == null) 573 return false; if (s.equals(".")) 575 break; if (s.length() > 1 && s.charAt(0) == '.' && s.charAt(1) == '.') { 577 s = s.substring(1); 579 } else if (s.startsWith("From ")) { 580 writer.write('>'); 582 } 583 writer.write(s); 584 writer.write('\n'); 585 } 586 session.setEcho(echo); 587 writer.write('\n'); 589 LocalMailboxEntry entry = new LocalMailboxEntry(entries.size()+1, 590 messageStart, sb.toString()); 591 entry.setNextMessageStart(writer.getOffset()); 592 entry.setSize(size); 593 entry.setFlags(MailboxEntry.RECENT); 594 entries.add(entry); 595 setDirty(true); 596 return true; } 598 catch (IOException e) { 599 Log.error(e); 600 return false; } 602 } 603 604 private boolean deleteMessagesOnServer(List serverMessageList) 605 { 606 Log.debug("deleteMessagesOnServer need to delete " + serverMessageList.size() + " messages"); 607 for (int i = 0; i < serverMessageList.size(); i++) { 608 MessageListEntry messageListEntry = 609 (MessageListEntry) serverMessageList.get(i); 610 session.write("dele " + messageListEntry.messageNumber); 611 String response = session.readLine(); 612 if (response == null || !response.startsWith("+OK")) { 613 Log.error("deleteMessagesOnServer dele failed response = " + response); 614 session.write("rset"); 615 session.readLine(); 616 return false; } 618 } 619 Log.debug("deleteMessagesOnServer success!"); 620 return true; 621 } 622 623 public void expunge() 624 { 625 if (lock()) { 626 setBusy(true); 627 saveDisplayState(); 628 Debug.assertTrue(backgroundThread == null); 629 backgroundThread = new Thread (expungeProcess); 630 backgroundThread.start(); 631 } 632 } 633 634 private Runnable expungeProcess = new BackgroundProcess() { 635 public void run() 636 { 637 try { 638 setBackgroundProcess(this); 639 progressNotifier = new StatusBarProgressNotifier(PopMailbox.this); 640 progressNotifier.progressStart(); 641 cancelled = false; 642 expungeInternal(); 643 } 644 finally { 645 setBackgroundProcess(null); 646 backgroundThread = null; 647 setBusy(false); 648 if (progressNotifier != null) { 649 if (cancelled) 650 progressNotifier.setText("Cancelled"); 651 progressNotifier.progressStop(); 652 progressNotifier = null; 653 } 654 unlock(); 655 updateDisplay(); 656 } 657 } 658 659 public void cancel() 660 { 661 Log.debug("expungeProcess.cancel"); 662 cancelled = true; 663 if (backgroundThread != null && backgroundThread.isAlive()) 664 backgroundThread.interrupt(); 665 session.disconnect(); 666 } 667 }; 668 669 private void expungeInternal() 670 { 671 if (entries == null) 672 return; if (getBooleanProperty(Property.POP_EXPUNGE_DELETED_MESSAGES_ON_SERVER) == false || 674 getBooleanProperty(Property.POP_KEEP_MESSAGES_ON_SERVER) == false) { 675 Log.debug("expungeInternal \"local expunge only\" case"); 677 for (int i = entries.size() - 1; i >= 0; i--) { 679 MailboxEntry entry = (MailboxEntry) entries.get(i); 680 if (entry.isDeleted()) 681 addToExpungedUidlsList(entry.getUidl()); 682 } 683 writeExpungedUidlsList(); rewriteMailbox(true); refreshBuffer(); 686 return; 687 } 688 Log.debug("expungeInternal \"expunge through\" case"); 690 if (!connect()) { 691 Log.error("expungeInternal can't connect"); 692 return; 693 } 694 try { 695 int count = stat(); 696 if (count < 0) 697 return; if (count > 0) { 699 List serverMessageList = getServerMessageList(count); 700 for (int i = 0; i < entries.size(); i++) { 701 MailboxEntry entry = (MailboxEntry) entries.get(i); 702 if (entry.isDeleted()) { 703 String uidl = entry.getUidl(); 704 if (!expungeUidl(uidl, serverMessageList)) 705 return; if (cancelled) { 707 progressNotifier.setText("Cancelled"); 708 return; 709 } 710 } 711 } 712 if (expungedUidlsList != null) { 713 Iterator it = expungedUidlsList.iterator(); 715 while (it.hasNext()) { 716 String uidl = (String ) it.next(); 717 if (!expungeUidl(uidl, serverMessageList)) 718 return; if (cancelled) { 720 progressNotifier.setText("Cancelled"); 721 return; 722 } 723 } 724 } 725 } 726 progressNotifier.progress("Logging out..."); 727 if (!session.logout()) 728 return; progressNotifier.progress("Saving mailbox..."); 731 rewriteMailbox(true); progressNotifier.setText("Saving mailbox...done"); 733 refreshBuffer(); 734 } 735 finally { 736 session.disconnect(); 737 } 738 } 739 740 private boolean expungeUidl(String uidl, List serverMessageList) 741 { 742 if (uidl != null) { 743 for (int j = serverMessageList.size() - 1; j >= 0; j--) { 744 MessageListEntry messageListEntry = (MessageListEntry) serverMessageList.get(j); 745 if (uidl.equals(messageListEntry.uidl)) { 746 if (progressNotifier != null) { 747 FastStringBuffer sb = new FastStringBuffer("Deleting message "); 748 sb.append(messageListEntry.messageNumber); 749 sb.append(" on server"); 750 progressNotifier.progress(sb.toString()); 751 } 752 session.write("dele " + messageListEntry.messageNumber); 753 String response = session.readLine(); 754 if (response != null && response.startsWith("+OK")) 755 return true; 756 Log.error("expungeUidl dele failed response = " + response); 758 session.write("rset"); 759 session.readLine(); 760 return false; 761 } 762 } 763 } 764 return true; 766 } 767 768 private HashSet expungedUidlsList; 769 770 private final boolean isExpunged(String uidl) 771 { 772 if (expungedUidlsList == null) 773 return false; 774 return expungedUidlsList.contains(uidl); 775 } 776 777 private final void addToExpungedUidlsList(String uidl) 778 { 779 if (expungedUidlsList == null) 780 expungedUidlsList = new HashSet (); 781 expungedUidlsList.add(uidl); 782 } 783 784 private void pruneExpungedUidlsList(List serverMessageList) 787 { 788 Log.debug("pruneExpungedUidlsList"); 789 if (expungedUidlsList == null) 790 return; boolean changed = false; 792 long start = System.currentTimeMillis(); 793 int size = serverMessageList.size(); 794 HashSet serverUidls = new HashSet (size); 795 for (int i = 0; i < size; i++) { 796 MessageListEntry entry = (MessageListEntry) serverMessageList.get(i); 797 serverUidls.add(entry.uidl); 798 } 799 Iterator it = expungedUidlsList.iterator(); 800 while (it.hasNext()) { 801 String uidl = (String ) it.next(); 802 if (!serverUidls.contains(uidl)) { 803 Log.warn("removing uidl " + uidl + " (no longer exists on server)"); 804 it.remove(); 805 changed = true; 806 } 807 } 808 if (changed) 809 writeExpungedUidlsList(); 810 Log.debug("pruneExpungedUidlsList " + (System.currentTimeMillis() - start) + " ms"); 811 } 812 813 private void readExpungedUidlsList() 814 { 815 File mailboxFile = getMailboxFile(); 816 if (mailboxFile == null) { 817 Debug.bug("readExpungedUidlsList mailboxFile is null"); 818 return; 819 } 820 String filename = mailboxFile.canonicalPath() + ".expunged"; 821 try { 822 BufferedReader reader = new BufferedReader (new FileReader (filename)); 823 String s; 824 while ((s = reader.readLine()) != null) { 825 if (expungedUidlsList == null) 826 expungedUidlsList = new HashSet (); 827 expungedUidlsList.add(s); 828 } 829 reader.close(); 830 } 831 catch (FileNotFoundException e) { 832 } 834 catch (IOException e) { 835 Log.error(e); 836 } 837 } 838 839 private void writeExpungedUidlsList() 840 { 841 File mailboxFile = getMailboxFile(); 842 if (mailboxFile == null) { 843 Debug.bug("writeExpungedUidls mailboxFile is null"); 844 return; 845 } 846 String filename = mailboxFile.canonicalPath() + ".expunged"; 847 if (expungedUidlsList == null || expungedUidlsList.size() == 0) { 848 File file = File.getInstance(filename); 849 if (file.isFile()) 850 file.delete(); 851 return; 852 } 853 try { 854 BufferedWriter writer = new BufferedWriter (new FileWriter (filename)); 855 Iterator it = expungedUidlsList.iterator(); 856 while (it.hasNext()) { 857 writer.write((String ) it.next()); 858 writer.newLine(); 859 } 860 writer.flush(); 861 writer.close(); 862 } 863 catch (IOException e) { 864 Log.error(e); 865 } 866 } 867 868 private static final SimpleDateFormat df = 869 new SimpleDateFormat ("EEE MMM dd HH:mm:ss yyyy", Locale.US); 870 871 private final String getDateTimeStamp() 872 { 873 return df.format(Calendar.getInstance().getTime()); 874 } 875 876 private File getLocalStore() 877 { 878 if (localStore != null) 879 return localStore; 880 File popDir = File.getInstance(Directories.getMailDirectory(), "pop"); 881 if (!popDir.isDirectory()) { 882 popDir.mkdirs(); 883 if (!popDir.isDirectory()) { 884 Log.error("can't make directory " + popDir.canonicalPath()); 885 return null; 886 } 887 } 888 File catalogFile = File.getInstance(popDir, "catalog"); 889 Properties catalog = new Properties (); 890 try { 892 if (catalogFile.isFile()) { 893 InputStream in = catalogFile.getInputStream(); 894 catalog.load(in); 895 in.close(); 896 } 897 } 898 catch (IOException e) { 899 Log.error(e); 900 } 901 String mailboxName = getUrl().toString(); 902 if (mailboxName.startsWith("pop://")) 903 mailboxName = mailboxName.substring(6); 904 String filename = catalog.getProperty(mailboxName); 905 if (filename != null) return localStore = File.getInstance(popDir, filename); 907 File file = Utilities.getTempFile(popDir); 908 catalog.put(mailboxName, file.getName()); 909 try { 910 OutputStream out = catalogFile.getOutputStream(); 911 catalog.save(out, null); 912 out.flush(); 913 out.close(); 914 return localStore = file; 915 } 916 catch (IOException e) { 917 Log.error(e); 918 return null; 919 } 920 } 921 922 public void dispose() 923 { 924 Log.debug("PopMailbox.dispose"); 925 Runnable disposeRunnable = new Runnable () { 926 public void run() 927 { 928 try { 929 Log.debug("disposeRunnable.run() calling acquire()..."); 930 acquire(); Log.debug("disposeRunnable.run() back from acquire()"); 932 if (dirty) { 933 final Object pending = new Object (); 934 Editor.getPendingOperations().add(pending); 935 Log.debug("disposeRunnable.run() calling rewriteMailbox()..."); 936 rewriteMailbox(false); 937 Log.debug("disposeRunnable.run() back from rewriteMailbox()"); 938 Editor.getPendingOperations().remove(pending); 939 } 940 Debug.assertTrue(session != null); 941 Log.debug("disposeRunnable.run() calling session.logout()..."); 942 session.logout(); 943 release(); 944 Log.debug("disposeRunnable.run() back from release()"); 945 } 946 catch (InterruptedException e) { 947 Log.error(e); 948 } 949 } 950 }; 951 new Thread (disposeRunnable).start(); 952 MailboxProperties.saveProperties(this); 953 } 954 955 protected void finalize() throws Throwable  956 { 957 Log.debug("PopMailbox.finalize"); 958 super.finalize(); 959 } 960 961 public String toString() 962 { 963 int newMessageCount = getNewMessageCount(); 964 if (newMessageCount > 0) { 965 FastStringBuffer sb = new FastStringBuffer(url.toString()); 966 sb.append(" ("); 967 sb.append(newMessageCount); 968 sb.append(" new)"); 969 return sb.toString(); 970 } else 971 return url.toString(); 972 } 973 974 public String getTitle() 975 { 976 return toString(); 977 } 978 } 979 980 class MessageListEntry 981 { 982 int messageNumber; 983 String uidl; 984 985 MessageListEntry(int messageNumber, String uidl) 986 { 987 this.messageNumber = messageNumber; 988 this.uidl = uidl; 989 } 990 } 991 | Popular Tags |