emailservices/emailclientapi/src/emailclientapiimpl.cpp
changeset 0 8466d47a6819
child 8 e1b6206813b4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/emailclientapi/src/emailclientapiimpl.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,435 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: This file implements class CEmailClientApi.
+*
+*/
+
+
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <viewclipartner.h>
+#include <vwsdefpartner.h>
+#else
+#include <viewcli.h>
+#include <vwsdef.h>
+#endif // SYMBIAN_ENABLE_SPLIT_HEADERS
+
+#include "emailclientapiimpl.h"
+#include "emailapiutils.h"
+#include "emailmailbox.h"
+#include <memailaddress.h>
+#include "CFSMailPlugin.h"
+#include "CFSClientAPI.h"
+#include "emailclientapiimpldefs.h"
+#include "emailmailboxcache.h"
+#include "FreestyleEmailUiConstants.h"
+#include "emailclientapi.hrh"
+// ---------------------------------------------------------------------------
+// CEmailClientApi::MailboxL
+// ---------------------------------------------------------------------------
+//
+MEmailMailbox* CEmailClientApi::MailboxL( const TMailboxId& aId )
+    {
+    UpdateMailboxInfoCacheL();
+    CPluginData* pluginData = MailboxInfoCacheL().PluginDataL( aId );
+    MEmailMailbox* mailbox = NULL;
+    if ( pluginData )
+        {
+        mailbox = CEmailMailbox::NewL( *pluginData, aId );
+        }
+    return mailbox;
+    }
+
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+MEmailMailbox* CEmailClientApi::MailboxL( const TPtrC& aAddress )
+    {
+    MEmailMailbox* mailbox = NULL;
+    REmailMailboxIdArray mailboxes;
+    CleanupClosePushL( mailboxes );
+    TInt count( GetMailboxIdsL( mailboxes ) );
+    while ( count-- )
+        {
+        const TMailboxId mailboxId = mailboxes[count];
+        MEmailMailbox* refMailbox = MailboxL( mailboxId );
+        if ( refMailbox )
+            {
+            TPtrC address( refMailbox->AddressL()->Address() );
+            if ( !address.Compare( aAddress ) )
+                {
+                mailbox = refMailbox; // addresses match
+                count = 0;
+                }
+            else
+                {
+                refMailbox->Release();
+                }
+            }
+        }
+    CleanupStack::PopAndDestroy();
+    // find mailbox or leave KErrNotFound
+    if ( !mailbox)
+        {
+        User::Leave( KErrNotFound );
+        }
+    return mailbox;
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+TInt CEmailClientApi::GetMailboxIdsL( 
+    REmailMailboxIdArray& aMailboxes )
+    {
+    UpdateMailboxInfoCacheL();
+
+    aMailboxes.Reset();
+    CEmailMailboxCache& mbcache = MailboxInfoCacheL();
+    mbcache.GetIdsL( aMailboxes ); 
+
+    const TInt mailboxesFound( aMailboxes.Count() );
+    return mailboxesFound;
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+TInt CEmailClientApi::GetMailboxesL( RMailboxPtrArray& aMailboxes )
+    {
+    REmailMailboxIdArray mailboxIdArray;
+    CleanupClosePushL( mailboxIdArray );
+    
+    // note! GetMailboxIdsL loads plugin and keeps loaded if it contains at
+    // least one mailbox
+    TInt count = GetMailboxIdsL( mailboxIdArray );
+    while ( count-- )
+        {
+        // mailbox creation increases plugin ref count by one
+        MEmailMailbox* mailbox = MailboxL( mailboxIdArray[count] );
+        CleanupReleasePushL( *mailbox );
+        aMailboxes.AppendL( mailbox );
+        CleanupStack::Pop( mailbox );
+        }
+    // Created mailboxes still hold plugin references so we can decrease 
+    // ref count.
+    ReleaseAllPlugins(); 
+    
+    CleanupStack::PopAndDestroy(); // mailboxIdArray
+    return aMailboxes.Count();
+    }
+
+// -----------------------------------------------------------------------------
+// implement this
+// -----------------------------------------------------------------------------
+void CEmailClientApi::LaunchEmailL( const TLaunchPolicy aPolicy )
+    {
+    if ( aPolicy != EDefault )
+        {
+        // no other launch policies supported
+        User::Leave( KErrNotSupported );
+        }
+    const TUid dummy = {0};
+                
+    CVwsSessionWrapper* viewSrvSession = CVwsSessionWrapper::NewLC();
+    viewSrvSession->ActivateView(TVwsViewId(KFSEmailUiUid, AppGridId),
+        dummy, KNullDesC8() );
+    CleanupStack::PopAndDestroy();    
+    }    
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+CPluginData* CEmailClientApi::TPluginIterator::Next()
+    {
+    CPluginData* item = NULL;
+    if ( iIndex < iArray.Count() )
+        {
+        item = iArray[ iIndex++ ];
+        }
+    return item;
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+CEmailClientApi* CEmailClientApi::NewL()
+    {
+    CEmailClientApi* self = new ( ELeave ) CEmailClientApi();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+CEmailClientApi::~CEmailClientApi()
+    {
+    // ensure this doesn't held plugin references
+    ReleaseAllPlugins();
+
+    // ResetAndDestroy doesn't work because ~CPluginData is private
+    TInt count( iPluginDataArray.Count() );
+    while ( count-- )
+        {
+        delete iPluginDataArray[count];
+        }
+    iPluginDataArray.Close();
+    iLoadedPluginsArray.Close();
+    delete iMailboxCache;
+    delete iClientAPI;
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+CEmailClientApi::CEmailClientApi()
+    {        
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+void CEmailClientApi::CleanupImplInfoPushL( RPointerArray<CImplementationInformation>& aArray )
+    {
+    TCleanupItem item( &CEmailClientApi::CleanupImplInfo, &aArray );
+    CleanupStack::PushL( item );
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+void CEmailClientApi::CleanupImplInfo( TAny* aAny )
+    {
+    RPointerArray<CImplementationInformation>* array = 
+        reinterpret_cast<RPointerArray<CImplementationInformation>*>( aAny );
+    array->ResetAndDestroy();
+    }
+ 
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+void CEmailClientApi::ConstructL()
+    {
+    RPointerArray<CImplementationInformation> implInfoArray;
+    REComSession::ListImplementationsL( KFSMailPluginInterface, implInfoArray );
+    CleanupImplInfoPushL( implInfoArray );
+    TInt err = KErrNone;
+    TInt count( implInfoArray.Count() );
+    // add implementation UIDs to plugin info array, no instantiation at this
+    // phase
+    while ( count-- )
+        {
+        const CImplementationInformation* info = implInfoArray[count];
+        CPluginData* pluginData = new ( ELeave ) CPluginData( info->ImplementationUid() );
+        err = iPluginDataArray.Append( pluginData );
+        if ( err != KErrNone )
+            {
+            // failed to append, give up
+            delete pluginData;
+            count = 0;
+            }
+        }
+    iClientAPI = CFSClientAPI::NewL(this);
+    CleanupStack::PopAndDestroy(); // CleanupImplInfoPushL
+    User::LeaveIfError( err );    
+    }
+
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+TEmailTypeId CEmailClientApi::InterfaceId() const
+    {
+    return KEmailClientApiInterface;
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+void CEmailClientApi::Release()
+    {
+    delete this;
+    }
+       
+// -----------------------------------------------------------------------------
+// Returns plugin instance from plugin data. If we already have "claimed"
+// instance once, prevent increment of reference count 
+// -----------------------------------------------------------------------------
+CFSMailPlugin* CEmailClientApi::UsePlugin( CPluginData& aPluginData )
+    {
+    // use 'data' as search key for IndexOfLoadedPluginData()
+    TPluginData data( aPluginData.Uid() );
+    TPluginData* pluginDataPtr = &data;
+    // check if we have plugin already "in use".
+    const TInt index( IndexOfLoadedPluginData( data ) );
+    if ( index == KErrNotFound )
+        { // we don't have plugin instance so take it and add to loaded plugins
+        data.iPlugin = aPluginData.ClaimInstance();
+        if ( data.iPlugin && iLoadedPluginsArray.Append( data ) != KErrNone )
+            {                
+            aPluginData.ReleaseInstance(); // failed to append, don't proceed..
+            data.iPlugin = NULL;           // but return null
+            }          
+        }
+    else
+        {
+        // already in use, obtain plugin pointer from the array
+        pluginDataPtr = &iLoadedPluginsArray[index];
+        }
+    return pluginDataPtr->iPlugin;
+    }
+    
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+void CEmailClientApi::ReleasePlugin( CPluginData& aPluginData )
+    {
+    // release plugin but only if it is not already claimed
+    TPluginData data( aPluginData.Uid() );
+    const TInt index( IndexOfLoadedPluginData( data ) );
+     if ( index != KErrNotFound )
+        {
+        aPluginData.ReleaseInstance();
+        iLoadedPluginsArray.Remove( index );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+void CEmailClientApi::ReleaseAllPlugins()
+    {
+    for ( TInt i = 0; i < iPluginDataArray.Count(); i++ )
+        {
+        CPluginData* pdata = iPluginDataArray[i];
+        ReleasePlugin( *pdata );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+CEmailMailboxCache& CEmailClientApi::MailboxInfoCacheL()
+    {
+    if ( !iMailboxCache) 
+        {
+        iMailboxCache = CEmailMailboxCache::NewL();
+        }
+    return *iMailboxCache;
+    }
+
+// -----------------------------------------------------------------------------
+// Lists all mailboxes in protocol plugins and adds them to cache. Plugins may 
+// not be loaded so loading is done. The plugin is kept in memory if it contains
+// at least one mailbox to avoid loading again later as typical use case is 
+// creation of a mailbox object => the plugin is again needed 
+//( see ::GetMailboxesL which calls ReleaseAllPlugins()
+// -----------------------------------------------------------------------------
+void CEmailClientApi::UpdateMailboxInfoCacheL()
+    {
+    CEmailMailboxCache& mbcache = MailboxInfoCacheL();
+    if ( !mbcache.IsCached() )
+        {
+        // cache update needed
+        mbcache.StartCachingPushL();
+        TPluginIterator iter( iPluginDataArray );
+        CPluginData* pluginData = iter.Next();
+        while ( pluginData )
+            {
+            TBool containsMailbox( EFalse );
+            // loads plugin if needed
+            CFSMailPlugin* plugin = UsePlugin( *pluginData );
+            if ( plugin )
+                {
+                // if one plugin fails, it should not block other plugins
+                // ==> trap it             
+                
+                TRAPD( err, containsMailbox = CachePluginMailboxesL(
+                    *pluginData, 
+                    *plugin ) );
+                if ( !containsMailbox || err )
+                    {
+                    // plugins with no mailboxes (or failed to cache) is
+                    // released (unloaded) to optimize RAM usage.
+                    ReleasePlugin( *pluginData );
+                    }            
+                }
+            else if ( pluginData->iPluginLoadError == KErrNoMemory )
+                {
+                // don't continue if OOM
+                User::Leave( KErrNoMemory );
+                }
+            pluginData = iter.Next();
+            }
+        mbcache.EndCachingPop();    
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+TBool CEmailClientApi::CachePluginMailboxesL( CPluginData& aPluginData, CFSMailPlugin& aPlugin )
+    {
+    TBool containsMailbox( EFalse );
+    RArray<TFSMailMsgId> pluginMailboxes;
+    CleanupClosePushL( pluginMailboxes );
+    aPlugin.ListMailBoxesL( pluginMailboxes );
+    TInt mailboxCount = pluginMailboxes.Count();
+    while ( mailboxCount-- )
+        {
+        const TFSMailMsgId& mailboxId = pluginMailboxes[mailboxCount];
+        TMailboxId id( mailboxId.Id() );                    
+        MailboxInfoCacheL().AddMailboxL( aPluginData, id );
+        containsMailbox = ETrue;
+        }
+    CleanupStack::PopAndDestroy();  // pluginMailboxes
+    return containsMailbox;
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+TInt CEmailClientApi::IndexOfLoadedPluginData( const TPluginData& aPluginData ) const
+    {
+    TIdentityRelation<TPluginData> relation( CEmailClientApi::PluginDataEquals );    
+    return iLoadedPluginsArray.Find( aPluginData, relation );
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+TBool CEmailClientApi::PluginDataEquals( const TPluginData& a1, const TPluginData& a2 )
+    {
+    return ( a1.iUid == a2.iUid );
+    }
+
+CFSMailPlugin* CEmailClientApi::GetPluginByUid(TUid aUid)
+    {
+    CPluginData *p = NULL;
+    CFSMailPlugin* plugin = NULL;
+
+    TRAP_IGNORE( p = iMailboxCache->PluginDataL(aUid) );
+    if ( p )
+        {
+        plugin = p->ClaimInstance();       
+        p->ReleaseInstance();
+        }
+    return plugin;
+    }
+
+// End of file.