emailservices/emailclientapi/src/emailclientapiimpl.cpp
changeset 54 997a02608b3a
child 62 a8c646b56683
equal deleted inserted replaced
53:bf7eb7911fc5 54:997a02608b3a
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: This file implements class CEmailClientApi.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    21 #include <viewclipartner.h>
       
    22 #include <vwsdefpartner.h>
       
    23 #else
       
    24 #include <viewcli.h>
       
    25 #include <vwsdef.h>
       
    26 #endif // SYMBIAN_ENABLE_SPLIT_HEADERS
       
    27 #include <centralrepository.h>
       
    28 #include "emailclientapiimpl.h"
       
    29 #include "emailapiutils.h"
       
    30 #include "emailmailbox.h"
       
    31 #include <memailaddress.h>
       
    32 #include "cfsmailplugin.h"
       
    33 #include "cfsmailclient.h"
       
    34 #include "emailclientapiimpldefs.h"
       
    35 #include "emailmailboxcache.h"
       
    36 #include "emailclientapi.hrh"
       
    37 
       
    38 // ---------------------------------------------------------------------------
       
    39 //
       
    40 // ---------------------------------------------------------------------------
       
    41 MEmailMailbox* CEmailClientApi::MailboxL( const TMailboxId& aId )
       
    42     {
       
    43     UpdateMailboxInfoCacheL();
       
    44     CPluginData* pluginData = MailboxInfoCacheL().PluginDataL( aId );
       
    45     MEmailMailbox* mailbox = NULL;
       
    46     if ( pluginData )
       
    47         {
       
    48         mailbox = CEmailMailbox::NewL( *pluginData, aId );
       
    49         }
       
    50     return mailbox;
       
    51     }
       
    52 
       
    53 // -----------------------------------------------------------------------------
       
    54 // 
       
    55 // -----------------------------------------------------------------------------
       
    56 MEmailMailbox* CEmailClientApi::MailboxL( const TPtrC& aAddress )
       
    57     {
       
    58     MEmailMailbox* mailbox = NULL;
       
    59     REmailMailboxIdArray mailboxes;
       
    60     CleanupClosePushL( mailboxes );
       
    61     TInt count( GetMailboxIdsL( mailboxes ) );
       
    62     while ( count-- )
       
    63         {
       
    64         const TMailboxId mailboxId = mailboxes[count];
       
    65         MEmailMailbox* refMailbox = MailboxL( mailboxId );
       
    66         if ( refMailbox )
       
    67             {
       
    68             TPtrC address( refMailbox->AddressL()->Address() );
       
    69             if ( !address.Compare( aAddress ) )
       
    70                 {
       
    71                 mailbox = refMailbox; // addresses match
       
    72                 count = 0;
       
    73                 }
       
    74             else
       
    75                 {
       
    76                 refMailbox->Release();
       
    77                 }
       
    78             }
       
    79         }
       
    80     CleanupStack::PopAndDestroy( &mailboxes );
       
    81     // find mailbox or leave KErrNotFound
       
    82     if ( !mailbox )
       
    83         {
       
    84         User::Leave( KErrNotFound );
       
    85         }
       
    86     return mailbox;
       
    87     }
       
    88 
       
    89 // -----------------------------------------------------------------------------
       
    90 // 
       
    91 // -----------------------------------------------------------------------------
       
    92 TInt CEmailClientApi::GetMailboxIdsL( 
       
    93     REmailMailboxIdArray& aMailboxes )
       
    94     {
       
    95     UpdateMailboxInfoCacheL();
       
    96 
       
    97     aMailboxes.Reset();
       
    98     CEmailMailboxCache& mbcache = MailboxInfoCacheL();
       
    99     mbcache.GetIdsL( aMailboxes ); 
       
   100 
       
   101     const TInt mailboxesFound( aMailboxes.Count() );
       
   102     return mailboxesFound;
       
   103     }
       
   104 
       
   105 // -----------------------------------------------------------------------------
       
   106 // 
       
   107 // -----------------------------------------------------------------------------
       
   108 TInt CEmailClientApi::GetMailboxesL( RMailboxPtrArray& aMailboxes )
       
   109     {
       
   110     REmailMailboxIdArray mailboxIdArray;
       
   111     CleanupClosePushL( mailboxIdArray );
       
   112 
       
   113     // GetMailboxIdsL loads plugin and keeps loaded if it contains at
       
   114     // least one mailbox
       
   115     TInt count = GetMailboxIdsL( mailboxIdArray );
       
   116     while ( count-- )
       
   117         {
       
   118         // mailbox creation increases plugin ref count by one
       
   119         MEmailMailbox* mailbox = MailboxL( mailboxIdArray[count] );
       
   120         CleanupReleasePushL( *mailbox );
       
   121         aMailboxes.AppendL( mailbox );
       
   122         CleanupStack::Pop( mailbox );
       
   123         }
       
   124     // Created mailboxes still hold plugin references so we can decrease 
       
   125     // ref count.
       
   126     ReleaseAllPlugins(); 
       
   127     
       
   128     CleanupStack::PopAndDestroy( &mailboxIdArray );
       
   129     return aMailboxes.Count();
       
   130     }
       
   131 
       
   132 // -----------------------------------------------------------------------------
       
   133 //
       
   134 // -----------------------------------------------------------------------------
       
   135 void CEmailClientApi::LaunchEmailL( const TLaunchPolicy /*aPolicy*/ )
       
   136     {
       
   137     User::Leave(KErrNotSupported);
       
   138     }
       
   139 
       
   140 // -----------------------------------------------------------------------------
       
   141 // 
       
   142 // -----------------------------------------------------------------------------
       
   143 CPluginData* CEmailClientApi::TPluginIterator::Next()
       
   144     {
       
   145     CPluginData* item = NULL;
       
   146     if ( iIndex < iArray.Count() )
       
   147         {
       
   148         item = iArray[ iIndex++ ];
       
   149         }
       
   150     return item;
       
   151     }
       
   152 
       
   153 // -----------------------------------------------------------------------------
       
   154 // 
       
   155 // -----------------------------------------------------------------------------
       
   156 CEmailClientApi* CEmailClientApi::NewL()
       
   157     {
       
   158     CEmailClientApi* instance = static_cast<CEmailClientApi*>( Dll::Tls() );
       
   159 
       
   160     if ( !instance )
       
   161         {
       
   162         instance = new ( ELeave ) CEmailClientApi();
       
   163         CleanupStack::PushL( instance );
       
   164         instance->ConstructL();
       
   165         User::LeaveIfError( Dll::SetTls( instance ) );
       
   166         CleanupStack::Pop( instance );
       
   167         }
       
   168 
       
   169     instance->iInstanceCounter++;
       
   170 
       
   171     return instance;
       
   172     }
       
   173 
       
   174 // -----------------------------------------------------------------------------
       
   175 // 
       
   176 // -----------------------------------------------------------------------------
       
   177 CEmailClientApi::~CEmailClientApi()
       
   178     {
       
   179     // ensure this doesn't held plugin references
       
   180     ReleaseAllPlugins();
       
   181 
       
   182     // ResetAndDestroy doesn't work because ~CPluginData is private
       
   183     TInt count( iPluginDataArray.Count() );
       
   184     while ( count-- )
       
   185         {
       
   186         delete iPluginDataArray[count];
       
   187         }
       
   188     iPluginDataArray.Close();
       
   189     iLoadedPluginsArray.Close();
       
   190     delete iMailboxCache;
       
   191 
       
   192     Dll::FreeTls();
       
   193     }
       
   194 
       
   195 // -----------------------------------------------------------------------------
       
   196 // 
       
   197 // -----------------------------------------------------------------------------
       
   198 CEmailClientApi::CEmailClientApi() : iInstanceCounter( 0 )
       
   199     {
       
   200     }
       
   201 
       
   202 // -----------------------------------------------------------------------------
       
   203 // 
       
   204 // -----------------------------------------------------------------------------
       
   205 void CEmailClientApi::CleanupImplInfoPushL( RPointerArray<CImplementationInformation>& aArray )
       
   206     {
       
   207     TCleanupItem item( &CEmailClientApi::CleanupImplInfo, &aArray );
       
   208     CleanupStack::PushL( item );
       
   209     }
       
   210 
       
   211 // -----------------------------------------------------------------------------
       
   212 // 
       
   213 // -----------------------------------------------------------------------------
       
   214 void CEmailClientApi::CleanupImplInfo( TAny* aAny )
       
   215     {
       
   216     RPointerArray<CImplementationInformation>* array = 
       
   217         reinterpret_cast<RPointerArray<CImplementationInformation>*>( aAny );
       
   218     array->ResetAndDestroy();
       
   219     }
       
   220  
       
   221 // -----------------------------------------------------------------------------
       
   222 // 
       
   223 // -----------------------------------------------------------------------------
       
   224 void CEmailClientApi::ConstructL()
       
   225     {
       
   226     RPointerArray<CImplementationInformation> implInfoArray;
       
   227     REComSession::ListImplementationsL( KFSMailPluginInterface, implInfoArray );
       
   228     CleanupImplInfoPushL( implInfoArray );
       
   229     TInt err = KErrNone;
       
   230     TInt count( implInfoArray.Count() );
       
   231     // add implementation UIDs to plugin info array, no instantiation at this
       
   232     // phase
       
   233     while ( count-- )
       
   234         {
       
   235         const CImplementationInformation* info = implInfoArray[count];
       
   236         CPluginData* pluginData = new ( ELeave ) CPluginData( info->ImplementationUid() );
       
   237         err = iPluginDataArray.Append( pluginData );
       
   238         if ( err != KErrNone )
       
   239             {
       
   240             // failed to append, give up
       
   241             delete pluginData;
       
   242             count = 0;
       
   243             }
       
   244         }
       
   245     iMailClient =  CFSMailClient::NewL();
       
   246     CleanupStack::PopAndDestroy( &implInfoArray );
       
   247     User::LeaveIfError( err );    
       
   248     }
       
   249 
       
   250 // -----------------------------------------------------------------------------
       
   251 // 
       
   252 // -----------------------------------------------------------------------------
       
   253 TEmailTypeId CEmailClientApi::InterfaceId() const
       
   254     {
       
   255     return KEmailClientApiInterface;
       
   256     }
       
   257 
       
   258 // -----------------------------------------------------------------------------
       
   259 // 
       
   260 // -----------------------------------------------------------------------------
       
   261 void CEmailClientApi::Release()
       
   262     {
       
   263     if( this->iInstanceCounter == 1 )
       
   264         {
       
   265         delete this;
       
   266         }
       
   267     else
       
   268         {
       
   269         this->iInstanceCounter--;
       
   270         }
       
   271     }
       
   272 
       
   273 // -----------------------------------------------------------------------------
       
   274 // Returns plugin instance from plugin data. If we already have "claimed"
       
   275 // instance once, prevent increment of reference count 
       
   276 // -----------------------------------------------------------------------------
       
   277 CFSMailPlugin* CEmailClientApi::UsePlugin( CPluginData& aPluginData )
       
   278     {
       
   279     // use 'data' as search key for IndexOfLoadedPluginData()
       
   280     TPluginData data( aPluginData.Uid() );
       
   281     TPluginData* pluginDataPtr = &data;
       
   282     // check if we have plugin already "in use".
       
   283     const TInt index( IndexOfLoadedPluginData( data ) );
       
   284     if ( index == KErrNotFound )
       
   285         { // we don't have plugin instance so take it and add to loaded plugins
       
   286         data.iPlugin = aPluginData.ClaimInstance();
       
   287         if ( data.iPlugin && iLoadedPluginsArray.Append( data ) != KErrNone )
       
   288             {                
       
   289             aPluginData.ReleaseInstance(); // failed to append, don't proceed..
       
   290             data.iPlugin = NULL;           // but return null
       
   291             }          
       
   292         }
       
   293     else
       
   294         {
       
   295         // already in use, obtain plugin pointer from the array
       
   296         pluginDataPtr = &iLoadedPluginsArray[index];
       
   297         }
       
   298     return pluginDataPtr->iPlugin;
       
   299     }
       
   300 
       
   301 // -----------------------------------------------------------------------------
       
   302 // 
       
   303 // -----------------------------------------------------------------------------
       
   304 void CEmailClientApi::ReleasePlugin( CPluginData& aPluginData )
       
   305     {
       
   306     // release plugin but only if it is not already claimed
       
   307     TPluginData data( aPluginData.Uid() );
       
   308     const TInt index( IndexOfLoadedPluginData( data ) );
       
   309      if ( index != KErrNotFound )
       
   310         {
       
   311         aPluginData.ReleaseInstance();
       
   312         iLoadedPluginsArray.Remove( index );
       
   313         }
       
   314     }
       
   315 
       
   316 // -----------------------------------------------------------------------------
       
   317 // 
       
   318 // -----------------------------------------------------------------------------
       
   319 void CEmailClientApi::ReleaseAllPlugins()
       
   320     {
       
   321     for ( TInt i = 0; i < iPluginDataArray.Count(); i++ )
       
   322         {
       
   323         CPluginData* pdata = iPluginDataArray[i];
       
   324         ReleasePlugin( *pdata );
       
   325         }
       
   326     }
       
   327 
       
   328 // -----------------------------------------------------------------------------
       
   329 // 
       
   330 // -----------------------------------------------------------------------------
       
   331 CEmailMailboxCache& CEmailClientApi::MailboxInfoCacheL()
       
   332     {
       
   333     if ( !iMailboxCache)
       
   334         {
       
   335         iMailboxCache = CEmailMailboxCache::NewL();
       
   336         }
       
   337     return *iMailboxCache;
       
   338     }
       
   339 
       
   340 // -----------------------------------------------------------------------------
       
   341 // Lists all mailboxes in protocol plugins and adds them to cache. Plugins may 
       
   342 // not be loaded so loading is done. The plugin is kept in memory if it contains
       
   343 // at least one mailbox to avoid loading again later as typical use case is 
       
   344 // creation of a mailbox object => the plugin is again needed 
       
   345 //( see ::GetMailboxesL which calls ReleaseAllPlugins()
       
   346 // -----------------------------------------------------------------------------
       
   347 void CEmailClientApi::UpdateMailboxInfoCacheL()
       
   348     {
       
   349     CEmailMailboxCache& mbcache = MailboxInfoCacheL();
       
   350     if ( !mbcache.IsCached() )
       
   351         {
       
   352         // cache update needed
       
   353         mbcache.StartCachingPushL();
       
   354         TPluginIterator iter( iPluginDataArray );
       
   355         CPluginData* pluginData = iter.Next();
       
   356         while ( pluginData )
       
   357             {
       
   358             TBool containsMailbox( EFalse );
       
   359             // loads plugin if needed
       
   360             CFSMailPlugin* plugin = UsePlugin( *pluginData );
       
   361             if ( plugin )
       
   362                 {
       
   363                 // if one plugin fails, it should not block other plugins
       
   364                 // ==> trap it             
       
   365                 
       
   366                 TRAPD( err, containsMailbox = CachePluginMailboxesL(
       
   367                     *pluginData, 
       
   368                     *plugin ) );
       
   369                 if ( !containsMailbox || err )
       
   370                     {
       
   371                     // plugins with no mailboxes (or failed to cache) is
       
   372                     // released (unloaded) to optimize RAM usage.
       
   373                     ReleasePlugin( *pluginData );
       
   374                     }            
       
   375                 }
       
   376             else if ( pluginData->iPluginLoadError == KErrNoMemory )
       
   377                 {
       
   378                 // don't continue if OOM
       
   379                 User::Leave( KErrNoMemory );
       
   380                 }
       
   381             pluginData = iter.Next();
       
   382             }
       
   383         mbcache.EndCachingPop();
       
   384         }
       
   385     }
       
   386 
       
   387 // -----------------------------------------------------------------------------
       
   388 // 
       
   389 // -----------------------------------------------------------------------------
       
   390 TBool CEmailClientApi::CachePluginMailboxesL( CPluginData& aPluginData, CFSMailPlugin& aPlugin )
       
   391     {
       
   392     TBool containsMailbox( EFalse );
       
   393     RArray<TFSMailMsgId> pluginMailboxes;
       
   394     CleanupClosePushL( pluginMailboxes );
       
   395     aPlugin.ListMailBoxesL( pluginMailboxes );
       
   396     TInt mailboxCount = pluginMailboxes.Count();
       
   397     while ( mailboxCount-- )
       
   398         {
       
   399         const TFSMailMsgId& mailboxId = pluginMailboxes[mailboxCount];
       
   400         TMailboxId id( mailboxId.Id() );
       
   401         MailboxInfoCacheL().AddMailboxL( aPluginData, id );
       
   402         containsMailbox = ETrue;
       
   403         }
       
   404     CleanupStack::PopAndDestroy( &pluginMailboxes );
       
   405     return containsMailbox;
       
   406     }
       
   407 
       
   408 // -----------------------------------------------------------------------------
       
   409 // 
       
   410 // -----------------------------------------------------------------------------
       
   411 TInt CEmailClientApi::IndexOfLoadedPluginData( const TPluginData& aPluginData ) const
       
   412     {
       
   413     TIdentityRelation<TPluginData> relation( CEmailClientApi::PluginDataEquals );
       
   414     return iLoadedPluginsArray.Find( aPluginData, relation );
       
   415     }
       
   416 
       
   417 // -----------------------------------------------------------------------------
       
   418 // 
       
   419 // -----------------------------------------------------------------------------
       
   420 TBool CEmailClientApi::PluginDataEquals( const TPluginData& a1, const TPluginData& a2 )
       
   421     {
       
   422     return ( a1.iUid == a2.iUid );
       
   423     }
       
   424 
       
   425 // End of file