Back to index

lightning-sunbird  0.9+nobinonly
nsImapMoveCoalescer.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "msgCore.h"
00039 #include "nsMsgImapCID.h"
00040 #include "nsImapMoveCoalescer.h"
00041 #include "nsMsgKeyArray.h"
00042 #include "nsIImapService.h"
00043 #include "nsIMsgCopyService.h"
00044 #include "nsMsgBaseCID.h"
00045 #include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later...
00046 #include "nsMsgFolderFlags.h"
00047 #include "nsIMsgHdr.h"
00048 #include "nsIEventQueueService.h"
00049 #include "nsIMsgImapMailFolder.h"
00050 
00051 static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
00052 
00053 NS_IMPL_ISUPPORTS1(nsImapMoveCoalescer, nsIUrlListener)
00054 
00055 nsImapMoveCoalescer::nsImapMoveCoalescer(nsIMsgFolder *sourceFolder, nsIMsgWindow *msgWindow)
00056 {
00057   m_sourceFolder = sourceFolder; 
00058   m_msgWindow = msgWindow;
00059   m_hasPendingMoves = PR_FALSE;
00060 }
00061 
00062 nsImapMoveCoalescer::~nsImapMoveCoalescer()
00063 {
00064   for (PRInt32 i = 0; i < m_sourceKeyArrays.Count(); i++)
00065   {
00066     nsMsgKeyArray *keys = (nsMsgKeyArray *) m_sourceKeyArrays.ElementAt(i);
00067     delete keys;
00068   }
00069   for (PRInt32 index = 0; index < m_keyBuckets.Count(); index++)
00070   {
00071     nsMsgKeyArray *keys = (nsMsgKeyArray *) m_keyBuckets.ElementAt(index);
00072     delete keys;
00073   }
00074 }
00075 
00076 nsresult nsImapMoveCoalescer::AddMove(nsIMsgFolder *folder, nsMsgKey key)
00077 {
00078   m_hasPendingMoves = PR_TRUE;
00079   if (!m_destFolders)
00080     NS_NewISupportsArray(getter_AddRefs(m_destFolders));
00081   if (m_destFolders)
00082   {
00083     nsCOMPtr <nsISupports> supports = do_QueryInterface(folder);
00084     if (supports)
00085     {
00086       PRInt32 folderIndex = m_destFolders->IndexOf(supports);
00087       nsMsgKeyArray *keysToAdd = nsnull;
00088       if (folderIndex >= 0)
00089       {
00090         keysToAdd = (nsMsgKeyArray *) m_sourceKeyArrays.ElementAt(folderIndex);
00091       }
00092       else
00093       {
00094         m_destFolders->AppendElement(supports);
00095         keysToAdd = new nsMsgKeyArray;
00096         if (!keysToAdd)
00097           return NS_ERROR_OUT_OF_MEMORY;
00098         
00099         m_sourceKeyArrays.AppendElement(keysToAdd);
00100       }
00101       if (keysToAdd && keysToAdd->IndexOf(key) == kNotFound)
00102         keysToAdd->Add(key);
00103       return NS_OK;
00104     }
00105     else
00106       return NS_ERROR_NULL_POINTER;
00107   }
00108   else
00109     return NS_ERROR_OUT_OF_MEMORY;
00110   
00111 }
00112 
00113 nsresult nsImapMoveCoalescer::PlaybackMoves(PRBool doNewMailNotification /* = PR_FALSE */)
00114 {
00115   PRUint32 numFolders;
00116   nsresult rv = NS_OK;
00117   if (!m_destFolders)
00118     return NS_OK;    // nothing to do.
00119   m_hasPendingMoves = PR_FALSE;
00120   m_doNewMailNotification = doNewMailNotification;
00121   m_destFolders->Count(&numFolders);
00122   m_outstandingMoves = 0;
00123   for (PRUint32 i = 0; i < numFolders; i++)
00124   {
00125     // XXX TODO
00126     // JUNK MAIL RELATED
00127     // is this the right place to make sure dest folder exists
00128     // (and has proper flags?), before we start copying?
00129     nsCOMPtr <nsIMsgFolder> destFolder(do_QueryElementAt(m_destFolders, i));
00130     nsCOMPtr<nsIImapService> imapService = 
00131       do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv);
00132     if (NS_SUCCEEDED(rv))
00133     {
00134       nsMsgKeyArray *keysToAdd = (nsMsgKeyArray *) m_sourceKeyArrays.ElementAt(i);
00135       if (keysToAdd)
00136       {
00137         PRInt32 numNewMessages = 0;
00138         PRInt32 numKeysToAdd = keysToAdd->GetSize();
00139         if (numKeysToAdd == 0)
00140           continue;
00141 
00142         nsCOMPtr<nsISupportsArray> messages;
00143         NS_NewISupportsArray(getter_AddRefs(messages));
00144         for (PRUint32 keyIndex = 0; keyIndex < keysToAdd->GetSize(); keyIndex++)
00145         {
00146           nsCOMPtr<nsIMsgDBHdr> mailHdr = nsnull;
00147           rv = m_sourceFolder->GetMessageHeader(keysToAdd->ElementAt(keyIndex), getter_AddRefs(mailHdr));
00148           if (NS_SUCCEEDED(rv) && mailHdr)
00149           {
00150             nsCOMPtr<nsISupports> iSupports = do_QueryInterface(mailHdr);
00151             messages->AppendElement(iSupports);
00152             PRBool isRead = PR_FALSE;
00153             mailHdr->GetIsRead(&isRead);
00154             if (!isRead)
00155               numNewMessages++;
00156           }
00157         }
00158         PRUint32 destFlags;
00159         destFolder->GetFlags(&destFlags);
00160         if (! (destFlags & MSG_FOLDER_FLAG_JUNK)) // don't set has new on junk folder
00161         {
00162           destFolder->SetNumNewMessages(numNewMessages);
00163           if (numNewMessages > 0)
00164             destFolder->SetHasNewMessages(PR_TRUE);
00165         }
00166         // adjust the new message count on the source folder
00167         PRInt32 oldNewMessageCount = 0;
00168         m_sourceFolder->GetNumNewMessages(PR_FALSE, &oldNewMessageCount);
00169         if (oldNewMessageCount >= numKeysToAdd)
00170           oldNewMessageCount -= numKeysToAdd;
00171         else
00172           oldNewMessageCount = 0;
00173 
00174         m_sourceFolder->SetNumNewMessages(oldNewMessageCount);
00175         
00176         nsCOMPtr <nsISupports> sourceSupports = do_QueryInterface(m_sourceFolder, &rv);
00177         nsCOMPtr <nsIUrlListener> urlListener(do_QueryInterface(sourceSupports));
00178         
00179         keysToAdd->RemoveAll();
00180         nsCOMPtr<nsIMsgCopyService> copySvc = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID);
00181         if (copySvc)
00182         {
00183           nsCOMPtr <nsIMsgCopyServiceListener> listener;
00184           if (m_doNewMailNotification)
00185           {
00186             nsMoveCoalescerCopyListener *copyListener = new nsMoveCoalescerCopyListener(this, destFolder);
00187             if (copyListener)
00188             {
00189               listener = do_QueryInterface(copyListener);
00190               NS_ADDREF(copyListener); // it will own its own reference
00191             }
00192           }
00193           rv = copySvc->CopyMessages(m_sourceFolder, messages, destFolder, PR_TRUE,
00194                                       listener, m_msgWindow, PR_FALSE /*allowUndo*/);
00195           if (NS_SUCCEEDED(rv))
00196             m_outstandingMoves++;
00197         }
00198       }
00199     }
00200   }
00201   return rv;
00202 }
00203 
00204 NS_IMETHODIMP
00205 nsImapMoveCoalescer::OnStartRunningUrl(nsIURI *aUrl)
00206 {
00207   NS_PRECONDITION(aUrl, "just a sanity check");
00208   return NS_OK;
00209 }
00210 
00211 NS_IMETHODIMP
00212 nsImapMoveCoalescer::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
00213 {
00214   m_outstandingMoves--;
00215   if (m_doNewMailNotification && !m_outstandingMoves)
00216   {
00217     nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(m_sourceFolder);
00218     if (imapFolder)
00219       imapFolder->NotifyIfNewMail();
00220   }
00221   return NS_OK;
00222 }
00223 
00224 nsMsgKeyArray *nsImapMoveCoalescer::GetKeyBucket(PRInt32 keyArrayIndex)
00225 {
00226   PRInt32 bucketCount = m_keyBuckets.Count();
00227   if (bucketCount < keyArrayIndex + 1)
00228   {
00229     for (PRInt32 i = 0; i < keyArrayIndex + 1 - bucketCount; i++)
00230     {
00231         nsMsgKeyArray *keysToAdd = new nsMsgKeyArray;
00232         if (!keysToAdd)
00233           return nsnull;
00234         
00235         m_keyBuckets.AppendElement(keysToAdd);
00236     }
00237   }
00238   return (nsMsgKeyArray *) m_keyBuckets.SafeElementAt(keyArrayIndex);
00239 }
00240 
00241 NS_IMPL_ISUPPORTS1(nsMoveCoalescerCopyListener, nsIMsgCopyServiceListener)
00242 
00243 nsMoveCoalescerCopyListener::nsMoveCoalescerCopyListener(nsImapMoveCoalescer * coalescer, 
00244                                                          nsIMsgFolder *destFolder)
00245 {
00246   m_destFolder = destFolder;
00247   m_coalescer = coalescer;
00248 }
00249 
00250 nsMoveCoalescerCopyListener::~nsMoveCoalescerCopyListener()
00251 {
00252 }
00253 
00254 NS_IMETHODIMP nsMoveCoalescerCopyListener::OnStartCopy()
00255 {
00256   return NS_ERROR_NOT_IMPLEMENTED;
00257 }
00258 
00259 /* void OnProgress (in PRUint32 aProgress, in PRUint32 aProgressMax); */
00260 NS_IMETHODIMP nsMoveCoalescerCopyListener::OnProgress(PRUint32 aProgress, PRUint32 aProgressMax)
00261 {
00262   return NS_ERROR_NOT_IMPLEMENTED;
00263 }
00264 
00265 /* void SetMessageKey (in PRUint32 aKey); */
00266 NS_IMETHODIMP nsMoveCoalescerCopyListener::SetMessageKey(PRUint32 aKey)
00267 {
00268   return NS_ERROR_NOT_IMPLEMENTED;
00269 }
00270 
00271 /* [noscript] void GetMessageId (in nsCString aMessageId); */
00272 NS_IMETHODIMP nsMoveCoalescerCopyListener::GetMessageId(nsCString * aMessageId)
00273 {
00274   return NS_ERROR_NOT_IMPLEMENTED;
00275 }
00276 
00277 /* void OnStopCopy (in nsresult aStatus); */
00278 NS_IMETHODIMP nsMoveCoalescerCopyListener::OnStopCopy(nsresult aStatus)
00279 {
00280   nsresult rv = NS_OK;
00281   if (NS_SUCCEEDED(aStatus))
00282   {
00283     // if the dest folder is imap, update it.
00284     nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(m_destFolder);
00285     if (imapFolder)
00286     {
00287       PRUint32 folderFlags;
00288       m_destFolder->GetFlags(&folderFlags);
00289       if (!(folderFlags & (MSG_FOLDER_FLAG_JUNK | MSG_FOLDER_FLAG_TRASH)))
00290       {
00291         nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv); 
00292         NS_ENSURE_SUCCESS(rv, rv);
00293         nsCOMPtr <nsIURI> url;
00294         nsCOMPtr<nsIEventQueueService> pEventQService = 
00295           do_GetService(kEventQueueServiceCID, &rv); 
00296         nsCOMPtr <nsIEventQueue> eventQueue;
00297         if (NS_SUCCEEDED(rv) && pEventQService)
00298           pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
00299           getter_AddRefs(eventQueue));
00300         nsCOMPtr <nsIUrlListener> listener = do_QueryInterface(m_coalescer);
00301         rv = imapService->SelectFolder(eventQueue, m_destFolder, listener, nsnull, getter_AddRefs(url));
00302       }
00303     }
00304     else // give junk filters a chance to run on new msgs in destination local folder
00305     {
00306       PRBool filtersRun;
00307       m_destFolder->CallFilterPlugins(nsnull, &filtersRun);
00308     }
00309   }
00310   return rv;
00311 }
00312 
00313 
00314