emailservices/emailstore/message_store/client/src/MessageStoreClient.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:39:21 +0200
changeset 0 8466d47a6819
child 8 e1b6206813b4
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2006 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:  Message store client session to the server.
*
*/



// ========
// INCLUDES
// ========

#include <e32svr.h>
#include <S32MEM.H>
//#include <MessageStoreClient.h>
//<cmail>
#include "msgstoretypes.h"
#include "debuglogmacros.h"
//</cmail>

#include "MessageStoreClientServer.h"
#include "EmailStoreUids.hrh"
#include "PropertiesSerializer.h"
#include "MsgStoreFolder.h"
#include "MsgStoreObserver.h"
#include "MsgStorePropertyContainerWithContent.h"
#include "MsgStoreSessionContext.h"

// =========
// CONSTANTS
// =========

//const TUint KSearchBufferLength = 30;


/** This class defines the message store search client API.

	This class is used to notify the search client of the completion of an asynchronous search of the
	message store.
*/
class MMsgStoreSearchClient
	{
	public:

		virtual void MatchFound( TMsgStoreId aMessageId ) = 0;
	
		virtual void SearchCompleted() = 0;
	
	}; // end class MMsgStoreSearchClient


/** This class defines the message store quick property client API.

	This class is used to notify the client when a quick property is ready to be processed, or
    to notify the client something has changed, restart building the list
*/
class MMsgStoreQuickPropertyClient
	{
	public:

		virtual void ProcessQuickProperty( const CMsgStorePropertyContainer& aContainer ) = 0;
	
		virtual void Reset() = 0;
	
	}; // end class MMsgStoreSearchClient


    
// ===============================
// CLASS: TPropertyContainerProxy
// ===============================
class TPropertyContainerProxy : public MPropertiesArray
    {
    public:
    
	    // ==============
	    // PUBLIC METHODS
	    // ==============
	    
        TPropertyContainerProxy( MMsgStoreQuickPropertyClient& aClient );
        
        // inherited from MPropertiesArray              
        virtual void AddElementL( TMsgStoreId aId, TMsgStoreId aParentId, const TDesC8& aProperties );
        virtual void Reset();        
        
    private:
    
	    // ==================
	    // PRIVATE ATTRIBUTES
	    // ==================
	
        MMsgStoreQuickPropertyClient& iClient;
        
    }; // end class TPropertyContainerProxy

    
// ======================
// METHOD IMPLEMENTATIONS
// ======================

// ----------------
// CMsgStoreSession
// ----------------

#if 0
// ==========================================================================
// FUNCTION: CopyAttachmentL
// ==========================================================================
EXPORT_C TMsgStoreId CMsgStoreSession::CopyAttachmentL( TMsgStoreId aAttachmentId,
		                                                TMsgStoreId aSourceMessageId, 
		                                                TMsgStoreId aSourceFolderId, 
		                                                TMsgStoreId aDestinationMessageId, 
		                                                TMsgStoreId aDestinationFolderId )
	{
	iContext->VerifyTypeL( aAttachmentId, EMsgStoreAttachmentBits );
	iContext->VerifyTypeL( aSourceMessageId, EMsgStoreMessageBits );
	iContext->VerifyTypeL( aSourceFolderId, EMsgStoreFolderBits );
	iContext->VerifyTypeL( aDestinationMessageId, EMsgStoreMessageBits );
	iContext->VerifyTypeL( aDestinationFolderId, EMsgStoreFolderBits );
	
	return iContext->iSession.CopyContainerL( aAttachmentId, 
	                                          aSourceMessageId, 
	                                          aSourceFolderId,
	                                          aDestinationMessageId,
	                                          aDestinationFolderId );	
	} // end CopyAttachmentL

// ==========================================================================
// FUNCTION: QuickMessagePropertiesL
// ==========================================================================
EXPORT_C void CMsgStoreSession::QuickMessagePropertiesL( TMsgStoreId aFolderId, RPointerArray<CMsgStorePropertyContainer>& aQuickProperties )
	{
	iContext->VerifyTypeL( aFolderId, EMsgStoreFolderBits );
	
	TPropertyContainersArray containersArray( aQuickProperties );
	
	iContext->iSession.ChildrenPropertiesL( aFolderId,            // aId
	                                        KMsgStoreInvalidId,   // aParentId (do not need to check parent ID)
	                                        EMsgStoreMessageBits, // aContainerType
	                                        ETrue,                // aQuickProperties
	                                        EFalse,               // aRecursive	                                        
	                                        containersArray );
	} // end QuickMessagePropertiesL
	
// ==========================================================================
// FUNCTION: QuickMessagePropertiesL overloaded
// ==========================================================================
EXPORT_C void CMsgStoreSession::QuickMessagePropertiesL( TMsgStoreId aFolderId, MMsgStoreQuickPropertyClient& aClient )
	{
	iContext->VerifyTypeL( aFolderId, EMsgStoreFolderBits );
	
	TPropertyContainerProxy containerProxy( aClient );
	
	iContext->iSession.ChildrenPropertiesL( aFolderId,            // aId
	                                        KMsgStoreInvalidId,   // aParentId (do not need to check parent ID)
	                                        EMsgStoreMessageBits, // aContainerType
	                                        ETrue,                // aQuickProperties
	                                        EFalse,               // aRecursive	                                        
	                                        containerProxy );
	} // end QuickMessagePropertiesL

// ==========================================================================
// FUNCTION: AttachmentsL
// ==========================================================================
EXPORT_C void CMsgStoreSession::AttachmentsL( TMsgStoreId                         aMessageId,
											  TMsgStoreId                         aFolderId,
										      RPointerArray<CMsgStoreAttachment>& aAttachmentsList )
	{
	iContext->VerifyTypeL( aMessageId, EMsgStoreMessageBits );
	iContext->VerifyTypeL( aFolderId, EMsgStoreFolderBits );

//	TAttachmentsArray attachmentsArray( *iContext, aAttachmentsList );
	
	iContext->iSession.ChildrenPropertiesL( aMessageId,              // aId
	                                        aFolderId,               // aParentId
	                                        EMsgStoreAttachmentBits, // aContainerType
	                                        EFalse,                  // aQuickProperties
	                                        EFalse,                  // aRecursive	                                        	                                        
	                                        attachmentsArray );	
	} // end AttachmentsL

// ==========================================================================
// FUNCTION: AttachmentL
// ==========================================================================
EXPORT_C CMsgStoreAttachment* CMsgStoreSession::AttachmentL( TMsgStoreId aAttachmentId,
										   				     TMsgStoreId aMessageId,
										   				     TMsgStoreId aFolderId )
	{
	iContext->VerifyTypeL( aAttachmentId, EMsgStoreAttachmentBits );
	iContext->VerifyTypeL( aMessageId, EMsgStoreMessageBits );
	iContext->VerifyTypeL( aFolderId, EMsgStoreFolderBits );
	
	RBuf8 propertiesBuf;
	CleanupClosePushL( propertiesBuf );
	
	iContext->iSession.ContainerPropertiesL( aAttachmentId, aMessageId, aFolderId, propertiesBuf );	

	CMsgStoreAttachment* attachment = CMsgStoreAttachment::NewL( *iContext, aAttachmentId, aMessageId, propertiesBuf );
	
	CleanupStack::PopAndDestroy( &propertiesBuf );
	
	return attachment;
	} // end AttachmentL

// ==========================================================================
// FUNCTION: AddAttachmentL
// ==========================================================================
EXPORT_C CMsgStoreAttachment* CMsgStoreSession::AddAttachmentL( TMsgStoreId                       aMessageId,
																TMsgStoreId                       aFolderId,
																const TDesC&                      aFilename, 
																const CMsgStorePropertyContainer& aProperties )
	{
	iContext->VerifyTypeL( aMessageId, EMsgStoreMessageBits );
	iContext->VerifyTypeL( aFolderId, EMsgStoreFolderBits );
	
	if( aFilename.Length() == 0 )
	    {
    	__LOG_STATIC_ENTER( "msg", "AddAttachmentL" )
    	__LOG_WRITE_ERROR( "zero length file name" )
	    __LOG_STATIC_EXIT
	    User::Leave( KErrArgument );
	    } // end if
	
	RBuf8 serializedProperties;
	CleanupClosePushL( serializedProperties );
	aProperties.SerializeL( serializedProperties );
	
	TInt id = iContext->iSession.CreateContainerL( aMessageId, 
												   aFolderId,
												   EMsgStoreAttachmentBits,
												   serializedProperties,
												   ETrue,
												   aFilename );
	
	CMsgStoreAttachment* attachment = CMsgStoreAttachment::NewL( *iContext, id, aMessageId, serializedProperties );
	
	CleanupStack::PopAndDestroy( &serializedProperties );
	
	return attachment;
	} // end AddAttachmentL

// ==========================================================================
// FUNCTION: AddAttachmentL
// ==========================================================================
EXPORT_C CMsgStoreAttachment* CMsgStoreSession::AddAttachmentL( TMsgStoreId                       aMessageId,
																TMsgStoreId                       aFolderId,
																const CMsgStorePropertyContainer& aProperties )
	{
	iContext->VerifyTypeL( aMessageId, EMsgStoreMessageBits );
	iContext->VerifyTypeL( aFolderId, EMsgStoreFolderBits );
	
	RBuf8 serializedProperties;
	CleanupClosePushL( serializedProperties );
	aProperties.SerializeL( serializedProperties );
	
	TInt id = iContext->iSession.CreateContainerL( aMessageId, 
												   aFolderId,
												   EMsgStoreAttachmentBits,
												   serializedProperties );
	
	CMsgStoreAttachment* attachment = CMsgStoreAttachment::NewL( *iContext, id, aMessageId, serializedProperties );
	
	CleanupStack::PopAndDestroy( &serializedProperties );
	
	return attachment;
	} // end AddAttachmentL

// ==========================================================================
// FUNCTION: RemoveAttachmentL
// ==========================================================================
EXPORT_C void CMsgStoreSession::RemoveAttachmentL( TMsgStoreId aAttachmentId,
												   TMsgStoreId aMessageId,
												   TMsgStoreId aFolderId )
	{
	iContext->VerifyTypeL( aMessageId, EMsgStoreMessageBits );
	iContext->VerifyTypeL( aFolderId, EMsgStoreFolderBits );
	iContext->VerifyTypeL( aAttachmentId, EMsgStoreAttachmentBits );
	
	iContext->iSession.DeleteContainerL( aAttachmentId, aMessageId, aFolderId );
	} // end RemoveAttachmentL
		
// ==========================================================================
// FUNCTION: SearchL
// ==========================================================================
EXPORT_C void CMsgStoreSession::SearchL( TMsgStoreId            aFolderId, 
                                         TMsgStoreSearchType    aSearchType, 
                					     const TDesC&           aSearchString,
                					     MMsgStoreSearchClient& aSearchClient )
    {
	iContext->VerifyTypeL( aFolderId, EMsgStoreFolderBits );

	if( aSearchString.Length() == 0 )
	    {
    	__LOG_STATIC_ENTER( "msg", "SearchL" )
    	__LOG_WRITE_ERROR( "zero length search string" )
        __LOG_STATIC_EXIT
        User::Leave( KErrArgument );
	    } // end if
    
    if( iContext->iSearchHandler )
        {
    	__LOG_STATIC_ENTER( "msg", "SearchL" )
    	__LOG_WRITE_ERROR( "search already in progress" )
        __LOG_STATIC_EXIT
        User::Leave( KErrInUse );
        } // end if        
	
    iContext->iSearchHandler = CMsgStoreSearchHandler::NewL( iContext->iSession, aFolderId, aSearchType, aSearchString, *this );
    iContext->iSearchClient  = &aSearchClient;
    
    } // end SearchL
									       
// ==========================================================================
// FUNCTION: CancelSearch
// ==========================================================================
EXPORT_C void CMsgStoreSession::CancelSearch()
    {
    delete iContext->iSearchHandler;
    iContext->iSearchHandler = NULL;
    iContext->iSearchClient  = NULL;
    } // end CancelSearch
    
// ==========================================================================
// FUNCTION: MatchFound
// ==========================================================================
void CMsgStoreSession::MatchFound( TMsgStoreId aMessageId )
    {
    iContext->iSearchClient->MatchFound( aMessageId );
    } // end MatchFound
    
// ==========================================================================
// FUNCTION: SearchCompleted
// ==========================================================================
void CMsgStoreSession::SearchCompleted()
    {
    delete iContext->iSearchHandler;
    iContext->iSearchHandler = NULL;
    
    iContext->iSearchClient->SearchCompleted();
    iContext->iSearchClient = NULL;
    } // end SearchCompleted
    
#endif

// ----------------------
// CMsgStoreSearchHandler
// ----------------------
#if 0
// ==========================================================================
// FUNCTION: NewL
// ==========================================================================
CMsgStoreSearchHandler* CMsgStoreSearchHandler::NewL( RMessageStoreSession&  aSession,
                                                      TMsgStoreId            aFolderId, 
                                                      TMsgStoreSearchType    aSearchType, 
                        					          const TDesC&           aSearchString,
                        					          MMsgStoreSearchClient& aSearchClient )
    {
    CMsgStoreSearchHandler* self = new(ELeave) CMsgStoreSearchHandler( aSession, aSearchClient );
    CleanupStack::PushL( self );
    self->ConstructL( aFolderId, aSearchType, aSearchString );
    CleanupStack::Pop( self );
    return self;
    } // end NewL
	
// ==========================================================================
// FUNCTION: Constructor
// ==========================================================================
CMsgStoreSearchHandler::CMsgStoreSearchHandler( RMessageStoreSession& aSession,
                                                MMsgStoreSearchClient& aSearchClient ) :
	CActive( EPriorityStandard ),
	iSession( aSession ),
    iSearchClient( aSearchClient )
    {
    __LOG_CONSTRUCT( "msg", "CMsgStoreSearchHandler" ) 
    
   	CActiveScheduler::Add(this);    
    } // end constructor
                			   
// ==========================================================================
// FUNCTION: ConstructL
// ==========================================================================
void CMsgStoreSearchHandler::ConstructL( TMsgStoreId           aFolderId, 
                                         TMsgStoreSearchType   aSearchType, 
		                                 const TDesC&          aSearchString )    
    {
    iMatchBuffer[0].CreateL( sizeof(TMsgStoreId) * KSearchBufferLength );
    iMatchBuffer[1].CreateL( sizeof(TMsgStoreId) * KSearchBufferLength );
    
    iSession.PrepareSearchL( aFolderId, aSearchType, aSearchString );
    
    iSession.GetMatchesL( iStatus, iMatchBuffer[iMatchBufferIndex] );
    SetActive();
    } // end ConstructL

// ==========================================================================
// FUNCTION: Destructor
// ==========================================================================
CMsgStoreSearchHandler::~CMsgStoreSearchHandler()
    {
    Cancel();
    
    iMatchBuffer[0].Close();
    iMatchBuffer[1].Close();
    
    if( iThisObjectHasBeenDeleted )
        {
        *iThisObjectHasBeenDeleted = ETrue;
        } // end if
        
    __LOG_DESTRUCT
    } // end destructor
	
// ==========================================================================
// FUNCTION: RunL
// ==========================================================================
void CMsgStoreSearchHandler::RunL()
    {
    __LOG_ENTER( "RunL" )
    
    RBuf8& currentMatchBuffer = iMatchBuffer[iMatchBufferIndex];
    
    if( iStatus == KErrNone && currentMatchBuffer.Length() > 0 )
    	{
    	// Switch to the other match buffer for the next call to the session.  Make this call before
    	// calling the search client with matches, just in case the client cancels the search during
    	// the callback.  This will cause DoCancel to be called during this object's destruction, which
    	// will cancel the server-side search.
    	iMatchBufferIndex = (iMatchBufferIndex + 1) % 2;
        iSession.GetMatchesL( iStatus, iMatchBuffer[iMatchBufferIndex] );
        SetActive();                                      

        // Client's may cancel the search during callbacks.  This flag mechanism is used to detect that case,
        // and avoid using any heap variables that may no longer be valid.
        TBool thisObjectHasBeenDeleted = EFalse;
        iThisObjectHasBeenDeleted = &thisObjectHasBeenDeleted;
            
    	TBool atEndOfIds = (currentMatchBuffer.Length() == 0);
    	TUint offset = 0;

    	while( !thisObjectHasBeenDeleted && !atEndOfIds )
    	    {
        	const TMsgStoreId& currentId = *reinterpret_cast<const TMsgStoreId *>( currentMatchBuffer.Ptr() + offset );
        	
            __LOG_WRITE8_FORMAT1_INFO( "match found (%i)", currentId )  
              
            offset += sizeof(TMsgStoreId);                    
            if( offset >= currentMatchBuffer.Length() )
                {
                atEndOfIds = ETrue;                
                } // end if
                
            // Note that the client may cancel the search during this callback.                    
            iSearchClient.MatchFound( currentId );                    
                                
    	    } // end while                    	    

        if( !thisObjectHasBeenDeleted )
            {
            iThisObjectHasBeenDeleted = NULL;
            } // end if
	    }
    else
    	{
        __LOG_WRITE8_FORMAT1_INFO( "Search completed, iStatus=%d", iStatus.Int() );
        
        iSearchClient.SearchCompleted();
        
    	} // end if       	

    // __LOG_EXIT was removed because it crashes in cases where thisObjectHasBeenDeleted is true    	
    
    } // end RunL
    
// ==========================================================================
// FUNCTION: RunError
// ==========================================================================
TInt CMsgStoreSearchHandler::RunError( TInt aError )
    {
    __LOG_ENTER_SUPPRESS( "RunError" )
    
    __LOG_WRITE8_FORMAT1_ERROR( "aError=%i", aError )
    
    // Something unexpected failed.  Notify the client that search is complete.
    iSearchClient.SearchCompleted();
    
    return KErrNone;
    
    } // end RunError

// ==========================================================================
// FUNCTION: DoCancel
// ==========================================================================
void CMsgStoreSearchHandler::DoCancel()
    {
    iSession.CancelSearch();
    } // end 
#endif
        
// ------------------------        
// TPropertyContainerProxy
// ------------------------        

// ==========================================================================
// FUNCTION: Constructor
// ==========================================================================
TPropertyContainerProxy::TPropertyContainerProxy( MMsgStoreQuickPropertyClient& aClient ) : 
    iClient( aClient ) 
    {
    } // end constructor
       
// ==========================================================================
// FUNCTION: AddElementL
// ==========================================================================
void TPropertyContainerProxy::AddElementL( TMsgStoreId aId, TMsgStoreId aParentId, const TDesC8& aProperties )
    {
    CMsgStorePropertyContainer *newContainer = CMsgStorePropertyContainer::NewL();
    CleanupStack::PushL( newContainer );

    newContainer->SetIds( aId, aParentId );
    newContainer->DeserializeL( aProperties );

    iClient.ProcessQuickProperty( *newContainer );    
    
    CleanupStack::PopAndDestroy( newContainer );
    } // end AddElementL
    
// ==========================================================================
// FUNCTION: Reset
// ==========================================================================
void TPropertyContainerProxy::Reset()
    {
    iClient.Reset();
    } // end Reset