Changeset 259
- Timestamp:
- 08/01/08 10:18:16 PM (4 months ago)
- Location:
- trunk/LogicMail/src/org/logicprobe/LogicMail
- Files:
-
- 10 modified
-
mail/AbstractMailStore.java (modified) (1 diff)
-
mail/FolderTreeItem.java (modified) (1 diff)
-
mail/imap/ImapClient.java (modified) (2 diffs)
-
mail/IncomingMailClient.java (modified) (1 diff)
-
mail/IncomingMailConnectionHandler.java (modified) (2 diffs)
-
mail/NetworkMailStore.java (modified) (2 diffs)
-
mail/pop/PopClient.java (modified) (1 diff)
-
model/AccountNode.java (modified) (9 diffs)
-
model/MailboxNode.java (modified) (6 diffs)
-
model/MailManager.java (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/AbstractMailStore.java
r253 r259 112 112 113 113 /** 114 * Requests the current message counts of a folder or 115 * group of folders. 116 * 117 * <p>Successful completion is indicated by a call to 114 * Requests the current message counts of a group of folders. 115 * 116 * <p>Successful completion is indicated by calls to 118 117 * {@link FolderListener#folderStatusChanged(FolderEvent)}. 119 118 * 120 * @param root The root node of the folder treeto refresh.121 */ 122 public abstract void requestFolderStatus(FolderTreeItem root);119 * @param folders The folder tree items to refresh. 120 */ 121 public abstract void requestFolderStatus(FolderTreeItem[] folders); 123 122 124 123 /** -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/FolderTreeItem.java
r221 r259 91 91 92 92 /** 93 * Create a folder tree item that is a clone of the source item, 94 * but has none of the references to parent or children items. 95 * 96 * @param source The source item. 97 */ 98 public FolderTreeItem(FolderTreeItem source) { 99 this.uniqueId = UniqueIdGenerator.getInstance().getUniqueId(); 100 this.name = source.name; 101 this.path = source.path; 102 this.delim = source.delim; 103 this.selectable = source.selectable; 104 this.msgCount = source.msgCount; 105 this.unseenCount = source.unseenCount; 106 } 107 108 /** 93 109 * Creates an uninitialized folder tree item. 94 110 * Only for use during deserialization. -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/imap/ImapClient.java
r253 r259 325 325 } 326 326 327 public void refreshFolderStatus(FolderTreeItem root) throws IOException, MailException { 328 // Flatten the tree for easy batching of the status refresh 329 Vector folders = new Vector(); 330 flattenFolderTree(folders, root); 331 327 public void refreshFolderStatus(FolderTreeItem[] folders) throws IOException, MailException { 332 328 // Construct an array of mailbox paths to match the folder vector 333 int size = folders.size();334 329 Vector mboxPaths = new Vector(); 335 330 Hashtable mboxMap = new Hashtable(); 336 331 int i; 337 for(i=0; i< size; i++) {338 FolderTreeItem item = (FolderTreeItem)folders.elementAt(i);332 for(i=0; i<folders.length; i++) { 333 FolderTreeItem item = folders[i]; 339 334 if(item.isSelectable()) { 340 335 mboxPaths.addElement(item.getPath()); … … 355 350 } 356 351 } 357 358 /**359 * Recursively walk the folder tree, populating a flat vector of360 * FolderTreeItem objects.361 *362 * @param folders An initialized Vector to populate363 * @param node The FolderTreeItem to start from364 */365 private void flattenFolderTree(Vector folders, FolderTreeItem node) {366 // Avoid adding the invisible root node367 if(node.getPath().length() > 0) {368 folders.addElement(node);369 }370 371 if(node.hasChildren()) {372 FolderTreeItem[] children = node.children();373 for(int i = 0; i < children.length; i++) {374 flattenFolderTree(folders, children[i]);375 }376 }377 }378 379 352 380 353 public FolderTreeItem getActiveFolder() { -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/IncomingMailClient.java
r172 r259 84 84 85 85 /** 86 * Refresh the folder status across the folder tree.86 * Refresh the folder status. 87 87 * 88 * @param root The root of the folder tree88 * @param folders The folders to refresh 89 89 * @throw IOException on I/O errors 90 90 * @throw MailException on protocol errors 91 91 */ 92 public abstract void refreshFolderStatus(FolderTreeItem root)92 public abstract void refreshFolderStatus(FolderTreeItem[] folders) 93 93 throws IOException, MailException; 94 94 -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/IncomingMailConnectionHandler.java
r253 r259 75 75 break; 76 76 case REQUEST_FOLDER_STATUS: 77 handleRequestFolderStatus((FolderTreeItem )params[0]);77 handleRequestFolderStatus((FolderTreeItem[])params[0]); 78 78 break; 79 79 case REQUEST_FOLDER_MESSAGES_RANGE: … … 126 126 } 127 127 128 private void handleRequestFolderStatus(FolderTreeItem root) throws IOException, MailException {129 incomingClient.refreshFolderStatus( root);130 131 MailConnectionHandlerListener listener = getListener(); 132 if(listener != null) { 133 listener.mailConnectionRequestComplete(REQUEST_FOLDER_STATUS, root);128 private void handleRequestFolderStatus(FolderTreeItem[] folders) throws IOException, MailException { 129 incomingClient.refreshFolderStatus(folders); 130 131 MailConnectionHandlerListener listener = getListener(); 132 if(listener != null) { 133 listener.mailConnectionRequestComplete(REQUEST_FOLDER_STATUS, folders); 134 134 } 135 135 } -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/NetworkMailStore.java
r253 r259 109 109 } 110 110 111 public void requestFolderStatus(FolderTreeItem root) {112 connectionHandler.addRequest(IncomingMailConnectionHandler.REQUEST_FOLDER_STATUS, new Object[] { root});111 public void requestFolderStatus(FolderTreeItem[] folders) { 112 connectionHandler.addRequest(IncomingMailConnectionHandler.REQUEST_FOLDER_STATUS, new Object[] { folders }); 113 113 } 114 114 … … 165 165 break; 166 166 case IncomingMailConnectionHandler.REQUEST_FOLDER_STATUS: 167 fireFolderStatusChanged((FolderTreeItem)result); 167 FolderTreeItem[] folders = (FolderTreeItem[])result; 168 for(int i=0; i<folders.length; i++) { 169 fireFolderStatusChanged(folders[i]); 170 } 168 171 break; 169 172 case IncomingMailConnectionHandler.REQUEST_FOLDER_MESSAGES_RANGE: -
trunk/LogicMail/src/org/logicprobe/LogicMail/mail/pop/PopClient.java
r245 r259 214 214 } 215 215 216 public void refreshFolderStatus(FolderTreeItem root) throws IOException, MailException {216 public void refreshFolderStatus(FolderTreeItem[] folders) throws IOException, MailException { 217 217 // Only one mailbox can exist, so we just pull the message counts 218 218 activeMailbox.setMsgCount(popProtocol.executeStat()); 219 if(folders.length == 1 && folders[0] != activeMailbox) { 220 folders[0].setMsgCount(activeMailbox.getMsgCount()); 221 } 219 222 } 220 223 -
trunk/LogicMail/src/org/logicprobe/LogicMail/model/AccountNode.java
r256 r259 31 31 package org.logicprobe.LogicMail.model; 32 32 33 import java.util.Enumeration; 33 34 import java.util.Hashtable; 34 35 import java.util.Vector; … … 51 52 import org.logicprobe.LogicMail.message.Message; 52 53 import org.logicprobe.LogicMail.message.MessageFlags; 54 import org.logicprobe.LogicMail.util.DataStore; 55 import org.logicprobe.LogicMail.util.DataStoreFactory; 53 56 import org.logicprobe.LogicMail.util.EventListenerList; 54 57 … … 74 77 private Vector outboundNewMessages = new Vector(); 75 78 private Hashtable outboundMessageReplies = new Hashtable(); 76 79 private DataStore accountDataStore; 80 77 81 public final static int STATUS_LOCAL = 0; 78 82 public final static int STATUS_OFFLINE = 1; … … 132 136 // Create the fake INBOX node for non-folder-capable mail stores 133 137 this.rootMailbox = new MailboxNode(new FolderTreeItem("", "", ""), -1); 138 this.rootMailbox.setParentAccount(this); 134 139 MailboxNode inboxNode = new MailboxNode(new FolderTreeItem("INBOX", "INBOX", ""), MailboxNode.TYPE_INBOX); 135 140 inboxNode.setParentAccount(this); … … 137 142 pathMailboxMap.put("INBOX", inboxNode); 138 143 } 144 145 // Load any saved tree data 146 load(); 139 147 } 140 148 … … 333 341 */ 334 342 public void refreshMailboxStatus() { 335 MailboxNode mailbox; 336 synchronized(rootMailboxLock) { 337 mailbox = this.rootMailbox; 338 } 339 mailStore.requestFolderStatus(mailbox.getFolderTreeItem()); 343 int size = pathMailboxMap.size(); 344 FolderTreeItem[] folders = new FolderTreeItem[size]; 345 Enumeration e = pathMailboxMap.keys(); 346 for(int i=0; i<size; i++) { 347 folders[i] = ((MailboxNode)pathMailboxMap.get(e.nextElement())).getFolderTreeItem(); 348 } 349 mailStore.requestFolderStatus(folders); 340 350 } 341 351 … … 408 418 } 409 419 420 save(); 410 421 fireAccountStatusChanged(AccountNodeEvent.TYPE_MAILBOX_TREE); 411 422 } … … 431 442 } 432 443 } 433 444 434 445 private void populateMailboxNodes(FolderTreeItem folderTreeItem, MailboxNode currentMailbox, Hashtable remainingMailboxMap) { 435 446 pathMailboxMap.put(folderTreeItem.getPath(), currentMailbox); … … 681 692 } 682 693 } 694 695 /** 696 * Saves the mailbox tree to persistent storage. 697 */ 698 private void save() { 699 if(accountConfig == null) { 700 return; 701 } 702 if(accountDataStore == null) { 703 long accountId = accountConfig.getUniqueId(); 704 accountDataStore = DataStoreFactory.getConnectionCacheStore(accountId); 705 accountDataStore.load(); 706 } 707 708 accountDataStore.putNamedObject("ROOT_MAILBOX", rootMailbox); 709 accountDataStore.save(); 710 } 711 712 /** 713 * Loads the mailbox tree from persistent storage. 714 */ 715 private void load() { 716 if(accountConfig == null) { 717 return; 718 } 719 if(accountDataStore == null) { 720 long accountId = accountConfig.getUniqueId(); 721 accountDataStore = DataStoreFactory.getConnectionCacheStore(accountId); 722 accountDataStore.load(); 723 } 724 725 Object loadedObject = accountDataStore.getNamedObject("ROOT_MAILBOX"); 726 if(loadedObject instanceof MailboxNode) { 727 synchronized(rootMailboxLock) { 728 this.rootMailbox = (MailboxNode)loadedObject; 729 this.rootMailbox.setParentAccount(this); 730 prepareDeserializedMailboxNode(rootMailbox); 731 } 732 } 733 } 734 735 //TODO: Handle deleted account nodes 736 737 /** 738 * Traverses the deserialized mailbox nodes, populates any necessary 739 * data structures in the account node, and sets the mailbox parent 740 * account references. 741 * 742 * @param mailboxNode The mailbox node. 743 */ 744 private void prepareDeserializedMailboxNode(MailboxNode mailboxNode) { 745 mailboxNode.setParentAccount(this); 746 FolderTreeItem item = mailboxNode.getFolderTreeItem(); 747 if(item != null && item.getPath().length() > 0) { 748 this.pathMailboxMap.put(item.getPath(), mailboxNode); 749 } 750 MailboxNode[] children = mailboxNode.getMailboxes(); 751 for(int i=0; i<children.length; i++) { 752 prepareDeserializedMailboxNode(children[i]); 753 } 754 } 683 755 } -
trunk/LogicMail/src/org/logicprobe/LogicMail/model/MailboxNode.java
r256 r259 31 31 package org.logicprobe.LogicMail.model; 32 32 33 import java.io.DataInputStream; 34 import java.io.DataOutputStream; 35 import java.io.IOException; 33 36 import java.util.Hashtable; 34 37 import java.util.Vector; … … 37 40 import org.logicprobe.LogicMail.mail.FolderTreeItem; 38 41 import org.logicprobe.LogicMail.util.EventListenerList; 42 import org.logicprobe.LogicMail.util.Serializable; 43 import org.logicprobe.LogicMail.util.UniqueIdGenerator; 39 44 40 45 /** … … 43 48 * <tt>MessageNode</tt> instances as its children. 44 49 */ 45 public class MailboxNode implements Node { 50 public class MailboxNode implements Node, Serializable { 51 private long uniqueId; 46 52 private AccountNode parentAccount; 47 53 private MailboxNode parentMailbox; … … 59 65 public final static int TYPE_TRASH = 4; 60 66 67 /** 68 * Initializes a new instance of <tt>MailboxNode</tt>. 69 * 70 * @param folderTreeItem The folder item this node wraps. 71 * @param type The type of mailbox this is representing. 72 */ 61 73 MailboxNode(FolderTreeItem folderTreeItem, int type) { 74 this.uniqueId = UniqueIdGenerator.getInstance().getUniqueId(); 62 75 this.mailboxes = new Vector(); 63 76 this.messages = new Vector(); 64 77 this.messageMap = new Hashtable(); 65 this.folderTreeItem = folderTreeItem; 78 if(folderTreeItem != null) { 79 this.setFolderTreeItem(new FolderTreeItem(folderTreeItem)); 80 } 66 81 this.type = type; 67 82 } 68 83 84 /** 85 * Initializes a new instance of <tt>MailboxNode</tt>. 86 * 87 * @param folderTreeItem The folder item this node wraps. 88 */ 69 89 MailboxNode(FolderTreeItem folderTreeItem) { 70 90 this(folderTreeItem, TYPE_NORMAL); 71 91 } 72 92 73 MailboxNode() { 93 /** 94 * Initializes a new instance of <tt>MailboxNode</tt>. 95 * 96 * <p><i>Note:</i> This constructor is only exposed for 97 * serialization purposes, and should never be called from 98 * outside this package for any other reason. 99 */ 100 public MailboxNode() { 74 101 this(null, TYPE_NORMAL); 75 102 } … … 121 148 * that maintain cache data for it. 122 149 * 150 * <p><i>Note:</i> The actual <tt>FolderTreeItem</tt> used by this 151 * class is a deep copy of the one passed to this method. It is 152 * implemented this way since we need a standalone object that 153 * is not part of a tree. This is necessary to avoid excessive 154 * recursion during serialization. 155 * 123 156 * @param folderTreeItem Folder tree item. 124 157 */ 125 158 void setFolderTreeItem(FolderTreeItem folderTreeItem) { 126 this.folderTreeItem = folderTreeItem;159 this.folderTreeItem = new FolderTreeItem(folderTreeItem); 127 160 } 128 161 … … 452 485 } 453 486 } 487 488 public long getUniqueId() { 489 return uniqueId; 490 } 491 492 public void serialize(DataOutputStream output) throws IOException { 493 output.writeLong(uniqueId); 494 output.writeInt(type); 495 folderTreeItem.serialize(output); 496 synchronized(mailboxes) { 497 int size = mailboxes.size(); 498 output.writeInt(size); 499 for(int i=0; i<size; i++) { 500 ((MailboxNode)mailboxes.elementAt(i)).serialize(output); 501 } 502 } 503 } 504 505 public void deserialize(DataInputStream input) throws IOException { 506 uniqueId = input.readLong(); 507 type = input.readInt(); 508 folderTreeItem = new FolderTreeItem(); 509 folderTreeItem.deserialize(input); 510 synchronized(mailboxes) { 511 int size = input.readInt(); 512 for(int i=0; i<size; i++) { 513 MailboxNode child = new MailboxNode(); 514 child.deserialize(input); 515 child.parentMailbox = this; 516 mailboxes.addElement(child); 517 } 518 } 519 } 454 520 } -
trunk/LogicMail/src/org/logicprobe/LogicMail/model/MailManager.java
r256 r259 108 108 return mailRootNode; 109 109 } 110 111 110 112 111 /** 113 112 * Called when the account configuration has changed,
