Changeset 582


Ignore:
Timestamp:
12/30/09 14:51:50 (2 years ago)
Author:
octorian
Message:

Expunge support for IMAP and Local folders. (still need post-delete cache scrub)

Location:
trunk/LogicMail/src/org/logicprobe/LogicMail
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/AbstractMailStore.java

    r529 r582  
    120120 
    121121    /** 
     122     * Returns whether the mail store supports expunging of deleted messages. 
     123     *  
     124     * @return True if expunge supported, false otherwise 
     125     */ 
     126    public abstract boolean hasExpunge(); 
     127     
     128    /** 
    122129     * Requests the regeneration of the mail folder tree. 
    123130     *  
     
    129136     */ 
    130137    public abstract void requestFolderTree(); 
     138     
     139    /** 
     140     * Requests that a folder be expunged of deleted messages. 
     141     *  
     142     * <p>Successful completion is indicated by a call to 
     143     * {@link FolderListener#folderStatusChanged(FolderEvent)}. 
     144     *  
     145     * @param folder The folder to expunge 
     146     */ 
     147    public abstract void requestFolderExpunge(FolderTreeItem folder); 
    131148     
    132149    /** 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/IncomingMailClient.java

    r562 r582  
    9292     
    9393    /** 
     94     * Return whether the underlying protocol supports expunging of deleted messages. 
     95     * 
     96     * @return True if expunge supported, false otherwise 
     97     */ 
     98    boolean hasExpunge(); 
     99     
     100    /** 
    94101     * Return whether the underlying protocol supports an idle connection mode. 
    95102     *  
     
    183190     */ 
    184191    void setActiveFolder(MessageToken messageToken) 
     192        throws IOException, MailException; 
     193     
     194    /** 
     195     * Expunges deleted messages from the currently active mail folder. 
     196     * This should do nothing if the underlying protocol does not support expunge. 
     197     * 
     198     * @throws IOException on I/O errors 
     199     * @throws MailException on protocol errors 
     200     */ 
     201    void expungeActiveFolder() 
    185202        throws IOException, MailException; 
    186203     
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/IncomingMailConnectionHandler.java

    r564 r582  
    4949        // "requestXXXX()" methods from AbstractMailStore 
    5050        public static final int REQUEST_FOLDER_TREE             = 10; 
    51         public static final int REQUEST_FOLDER_STATUS           = 11; 
    52         public static final int REQUEST_FOLDER_MESSAGES_RANGE   = 12; 
    53         public static final int REQUEST_FOLDER_MESSAGES_SET     = 13; 
    54         public static final int REQUEST_FOLDER_MESSAGES_RECENT  = 14; 
     51    public static final int REQUEST_FOLDER_EXPUNGE          = 11; 
     52        public static final int REQUEST_FOLDER_STATUS           = 12; 
     53        public static final int REQUEST_FOLDER_MESSAGES_RANGE   = 13; 
     54        public static final int REQUEST_FOLDER_MESSAGES_SET     = 14; 
     55        public static final int REQUEST_FOLDER_MESSAGES_RECENT  = 15; 
    5556        public static final int REQUEST_MESSAGE                 = 20; 
    5657        public static final int REQUEST_MESSAGE_PARTS           = 21; 
     
    9192                        handleRequestFolderTree(); 
    9293                        break; 
     94                case REQUEST_FOLDER_EXPUNGE: 
     95                    handleRequestFolderExpunge((FolderTreeItem)params[0]); 
     96                    break; 
    9397                case REQUEST_FOLDER_STATUS: 
    9498                        handleRequestFolderStatus((FolderTreeItem[])params[0]); 
     
    132136        } 
    133137 
    134         /** 
     138    /** 
    135139         * Handles the start of the IDLE state. 
    136140         */ 
     
    211215                } 
    212216        } 
    213          
     217 
     218    private void handleRequestFolderExpunge(FolderTreeItem folder) throws IOException, MailException { 
     219        String message = resources.getString(LogicMailResource.MAILCONNECTION_REQUEST_FOLDER_EXPUNGE); 
     220        showStatus(message); 
     221        checkActiveFolder(folder); 
     222        incomingClient.expungeActiveFolder(); 
     223         
     224        MailConnectionHandlerListener listener = getListener(); 
     225        if(listener != null) { 
     226            listener.mailConnectionRequestComplete(REQUEST_FOLDER_EXPUNGE, folder); 
     227        } 
     228    } 
     229     
    214230        private void handleRequestFolderStatus(FolderTreeItem[] folders) throws IOException, MailException { 
    215231                String message = resources.getString(LogicMailResource.MAILCONNECTION_REQUEST_FOLDER_STATUS); 
     
    243259            this.param = param; 
    244260            this.count = 0; 
    245              
    246261        } 
    247262         
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/LocalMailStore.java

    r581 r582  
    115115    } 
    116116 
     117    public boolean hasExpunge() { 
     118        return true; 
     119    } 
     120     
    117121    public void requestFolderTree() { 
    118122        fireFolderTreeUpdated(rootFolder); 
    119123    } 
    120124 
     125    public void requestFolderExpunge(FolderTreeItem folder) { 
     126        // TODO: Implement local expunge 
     127        FolderTreeItem requestFolder = getMatchingFolderTreeItem(folder.getPath()); 
     128         
     129        if(requestFolder != null) { 
     130            threadQueue.invokeLater(new ExpungeFolderRunnable(requestFolder)); 
     131        } 
     132    } 
     133     
     134    private class ExpungeFolderRunnable extends MaildirRunnable { 
     135        public ExpungeFolderRunnable(FolderTreeItem requestFolder) { 
     136            super(requestFolder); 
     137        } 
     138         
     139        public void run() { 
     140            FolderMessage[] folderMessages = null; 
     141            try { 
     142                maildirFolder.open(); 
     143                maildirFolder.expunge(); 
     144                maildirFolder.close(); 
     145            } catch (IOException e) { 
     146                System.err.println("Unable to expunge folder: " + e.toString()); 
     147            } 
     148             
     149            if(folderMessages != null) { 
     150                fireFolderStatusChanged(requestFolder); 
     151            } 
     152        } 
     153    } 
     154     
    121155    public void requestFolderStatus(FolderTreeItem[] folders) { 
    122156        // Make every entry in the provided array match the local folder 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/MaildirFolder.java

    r581 r582  
    480480        if(mailFileConnection.exists() && !mailFileConnection.isDirectory() && mailFileConnection.canRead()) { 
    481481            mailFileConnection.rename(updatedFilename); 
     482            mailFileConnection.close(); 
    482483            return true; 
    483484        } 
    484485        else { 
     486            mailFileConnection.close(); 
    485487            return false; 
     488        } 
     489    } 
     490 
     491    /** 
     492     * Remove all deleted messages from this folder. 
     493     */ 
     494    public void expunge() throws IOException { 
     495        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     496            EventLogger.logEvent(AppInfo.GUID, 
     497                ("expunge()").getBytes(), 
     498                EventLogger.DEBUG_INFO); 
     499        } 
     500 
     501        // Build a list of deleted files in the current directory 
     502        Vector deletedFiles = new Vector(); 
     503        Enumeration e = fileConnection.list(); 
     504        while(e.hasMoreElements()) { 
     505            String messageFilename = (String)e.nextElement(); 
     506            int p = messageFilename.indexOf('_'); 
     507            if(p != -1 && messageFilename.indexOf('T', p) != -1) { 
     508                deletedFiles.addElement(messageFilename); 
     509            } 
     510        } 
     511         
     512        // Iterate through the list and actually delete from storage 
     513        String baseUrl = fileConnection.getURL() + '/'; 
     514        e = deletedFiles.elements(); 
     515        while(e.hasMoreElements()) { 
     516            String messageFilename = (String)e.nextElement(); 
     517            try { 
     518                FileConnection mailFileConnection = 
     519                    (FileConnection)Connector.open(baseUrl + messageFilename); 
     520                if(mailFileConnection.exists() && !mailFileConnection.isDirectory() && mailFileConnection.canRead()) { 
     521                    mailFileConnection.delete(); 
     522                } 
     523                mailFileConnection.close(); 
     524            } catch (IOException exp) { 
     525                if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     526                    EventLogger.logEvent(AppInfo.GUID, 
     527                            ("Error deleting message: " + exp.toString()).getBytes(), 
     528                            EventLogger.DEBUG_INFO); 
     529                } 
     530            } 
    486531        } 
    487532    } 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/NetworkMailStore.java

    r529 r582  
    110110        } 
    111111 
     112        public boolean hasExpunge() { 
     113            return client.hasExpunge(); 
     114        } 
     115         
    112116        public boolean isConnected() { 
    113117                return client.isConnected(); 
     
    118122        } 
    119123 
     124        public void requestFolderExpunge(FolderTreeItem folder) { 
     125            connectionHandler.addRequest(IncomingMailConnectionHandler.REQUEST_FOLDER_EXPUNGE, new Object[] { folder }); 
     126        } 
     127         
    120128        public void requestFolderStatus(FolderTreeItem[] folders) { 
    121129                connectionHandler.addRequest(IncomingMailConnectionHandler.REQUEST_FOLDER_STATUS, new Object[] { folders }); 
     
    186194                        fireFolderTreeUpdated((FolderTreeItem)result); 
    187195                        break; 
     196                case IncomingMailConnectionHandler.REQUEST_FOLDER_EXPUNGE: 
     197                    fireFolderStatusChanged((FolderTreeItem)result); 
     198                    break; 
    188199                case IncomingMailConnectionHandler.REQUEST_FOLDER_STATUS: 
    189200                        FolderTreeItem[] folders = (FolderTreeItem[])result; 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/imap/ImapClient.java

    r580 r582  
    331331 
    332332    /* (non-Javadoc) 
     333     * @see org.logicprobe.LogicMail.mail.IncomingMailClient#hasExpunge() 
     334     */ 
     335    public boolean hasExpunge() { 
     336        return true; 
     337    } 
     338     
     339    /* (non-Javadoc) 
    333340     * @see org.logicprobe.LogicMail.mail.IncomingMailClient#hasAppend() 
    334341     */ 
     
    584591     
    585592    /* (non-Javadoc) 
     593     * @see org.logicprobe.LogicMail.mail.IncomingMailClient#expungeActiveFolder() 
     594     */ 
     595    public void expungeActiveFolder() throws IOException, MailException { 
     596        imapProtocol.executeExpunge(); 
     597    } 
     598     
     599    /* (non-Javadoc) 
    586600     * @see org.logicprobe.LogicMail.mail.IncomingMailClient#getFolderMessages(int, int, org.logicprobe.LogicMail.mail.FolderMessageCallback, org.logicprobe.LogicMail.mail.MailProgressHandler) 
    587601     */ 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/imap/ImapProtocol.java

    r562 r582  
    367367    } 
    368368 
     369    public void executeExpunge() throws IOException, MailException { 
     370        if (EventLogger.getMinimumLevel() >= EventLogger.DEBUG_INFO) { 
     371            EventLogger.logEvent(AppInfo.GUID, 
     372                ("ImapProtocol.executeExpunge()").getBytes(), 
     373                EventLogger.DEBUG_INFO); 
     374        } 
     375 
     376        execute("EXPUNGE", null, null); 
     377    } 
     378     
    369379    public StatusResponse[] executeStatus(String[] mboxpaths, MailProgressHandler progressHandler) 
    370380        throws IOException, MailException { 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/mail/pop/PopClient.java

    r564 r582  
    266266 
    267267    /* (non-Javadoc) 
     268     * @see org.logicprobe.LogicMail.mail.IncomingMailClient#hasExpunge() 
     269     */ 
     270    public boolean hasExpunge() { 
     271        return false; 
     272    } 
     273     
     274    /* (non-Javadoc) 
    268275     * @see org.logicprobe.LogicMail.mail.IncomingMailClient#hasAppend() 
    269276     */ 
     
    334341        // Mailbox cannot be changed, so we just pull the message counts 
    335342        activeMailbox.setMsgCount(popProtocol.executeStat()); 
     343    } 
     344     
     345    /* (non-Javadoc) 
     346     * @see org.logicprobe.LogicMail.mail.IncomingMailClient#expungeActiveFolder() 
     347     */ 
     348    public void expungeActiveFolder() throws IOException, MailException { 
     349        // Expunge is not supported, so we do nothing here. 
    336350    } 
    337351     
  • trunk/LogicMail/src/org/logicprobe/LogicMail/model/AccountNode.java

    r574 r582  
    346346 
    347347    /** 
     348     * Gets whether this account supports expunging deleted messages. 
     349     * 
     350     * @return True if supported, false otherwise. 
     351     */ 
     352    public boolean hasExpunge() { 
     353        return this.mailStore.hasExpunge(); 
     354    } 
     355 
     356    /** 
    348357     * Called to trigger a refresh of the mailboxes under 
    349358     * this account.  Completion is signaled by an 
  • trunk/LogicMail/src/org/logicprobe/LogicMail/model/MailboxNode.java

    r574 r582  
    690690 
    691691    /** 
     692     * Check if this mailbox has messages marked as deleted. 
     693     * This is the recommended way to check for deleted messages, 
     694     * since the UI may not always track such messages. 
     695     *  
     696     * @return True if deleted messages exist 
     697     */ 
     698    public boolean hasDeletedMessages() { 
     699        boolean hasDeleted = false; 
     700        synchronized(messages) { 
     701            int size = messages.size(); 
     702            for(int i=0; i<size; i++) { 
     703                int flags = ((MessageNode)messages.elementAt(i)).getFlags(); 
     704                if((flags & MessageNode.Flag.DELETED) != 0) { 
     705                    hasDeleted = true; 
     706                    break; 
     707                } 
     708            } 
     709        } 
     710        return hasDeleted; 
     711    } 
     712 
     713    /** 
     714     * Tells the underlying mail store to expunge any deleted messages 
     715     * from the mailbox, if possible. 
     716     */ 
     717    public void expungeDeletedMessages() { 
     718        parentAccount.getMailStore().requestFolderExpunge(this.folderTreeItem); 
     719    } 
     720 
     721    /** 
    692722     * Update the unseen message count from the local messages collection. 
    693723     *  
  • trunk/LogicMail/src/org/logicprobe/LogicMail/ui/MailboxScreen.java

    r551 r582  
    4141import net.rim.device.api.ui.MenuItem; 
    4242import net.rim.device.api.ui.Screen; 
     43import net.rim.device.api.ui.component.Dialog; 
    4344import net.rim.device.api.ui.component.Menu; 
    4445import net.rim.device.api.ui.container.VerticalFieldManager; 
     
    294295    } 
    295296 
     297     
     298    public boolean onClose() { 
     299        // Check for deleted messages in the mailbox 
     300        if(mailboxNode.getParentAccount().hasExpunge() 
     301                && mailboxNode.hasDeletedMessages()) { 
     302            // Prompt for expunge if possible and supported 
     303            int choice = Dialog.ask( 
     304                    Dialog.D_YES_NO, 
     305                    resources.getString(LogicMailResource.MAILBOX_EXPUNGE_PROMPT), 
     306                    Dialog.YES); 
     307             
     308            // Request expunge if desired 
     309            if(choice == Dialog.YES) { 
     310                mailboxNode.expungeDeletedMessages(); 
     311            } 
     312        } 
     313         
     314        // Close the screen 
     315        screen.close(); 
     316        return true; 
     317    } 
     318     
    296319    /** 
    297320     * Handles mailbox status change events. 
Note: See TracChangeset for help on using the changeset viewer.