contextframework/cfw/src/cfserver/CFContextManager.cpp
changeset 0 2e3d3ce01487
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contextframework/cfw/src/cfserver/CFContextManager.cpp	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,930 @@
+/*
+* Copyright (c) 2002-2008 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:  CCFContextManager class implementation.
+*
+*/
+
+
+#include <cfcontextdataobject.h>
+
+#include "CFContextManager.h"
+#include "CFContextQueryImpl.h"
+#include "CFContextObjectImpl.h"
+#include "cfcontextsubscriptionlistener.h"
+#include "CFContextSubscriptionImpl.h"
+#include "CFCacheElement.h"
+#include "cfutils.h"
+#include "cftrace.h"
+#include "CFContextDataProxy.h"
+#include "cfcommon.h"
+
+// Public Constructors and destructors
+CCFContextManager* CCFContextManager::NewL(
+	MCFSecurityChecker& aSecurityChecker )
+    {
+    FUNC_LOG;
+
+    CCFContextManager* self = CCFContextManager::NewLC( aSecurityChecker );
+    CleanupStack::Pop(self);
+
+    return self;
+    }
+
+CCFContextManager* CCFContextManager::NewLC(
+	MCFSecurityChecker& aSecurityChecker )
+    {
+    FUNC_LOG;
+
+    CCFContextManager* self
+    	= new (ELeave) CCFContextManager( aSecurityChecker );
+    CleanupStack::PushL(self);
+    self->ConstructL();
+
+    return self;
+    }
+
+CCFContextManager::~CCFContextManager()
+    {
+    FUNC_LOG;
+
+    iCleanupCacheElements.Close();
+    iContextCache.ResetAndDestroy();
+    iContextCache.Close();
+    delete iPreviousContext;
+    delete iCacheOrder;
+    delete iCacheSearchKey;
+
+    iSubscriptions.ResetAndDestroy();
+    }
+
+CCFContextManager::CCFContextManager( MCFSecurityChecker& aSecurityChecker )
+    {
+    FUNC_LOG;
+
+    iSecurityChecker = &aSecurityChecker;
+    }
+
+void CCFContextManager::ConstructL()
+    {
+    FUNC_LOG;
+
+    iCacheOrder = new (ELeave) TLinearOrder<CCFCacheElement>
+        (CCFCacheElement::CompareByTypeAndSource);
+
+    iCacheSearchKey = CCFCacheElement::NewL();
+
+    iPreviousContext = CCFContextObject::NewL();
+    }
+
+// METHODS
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::PublishContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::PublishContextL( CCFContextObject &aContext,
+    RThread& aClientThread )
+    {
+    FUNC_LOG;
+
+    ValidatePublishContextL( aContext, aClientThread );
+    DoPublishContextL( aContext );
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::PublishContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::PublishContextL( CCFContextObject &aContext,
+    RThread& aClientThread,
+    CCFContextDataObject& aData )
+    {
+    FUNC_LOG;
+
+    ValidatePublishContextL( aContext, aClientThread );
+    DoPublishContextL( aContext, &aData );
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::RequestContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::RequestContextL( RContextObjectArray& aResultBuffer,
+    CCFContextQuery& aContextQuery,
+    RThread& aClientThread )
+    {
+    FUNC_LOG;
+
+    // Accessing the context cache for the latest context values is enough
+    DoRequestContextL( aResultBuffer, aContextQuery, &aClientThread );
+    }
+
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::RequestContextL
+//-----------------------------------------------------------------------------
+//
+CCFContextObject* CCFContextManager::RequestContextL( const TDesC& aContextType,
+    const TDesC& aContextSource,
+    RThread& aClientThread )
+    {
+    FUNC_LOG;
+
+    // check the cache
+    iCacheSearchKey->Context().SetTypeL( aContextType );
+    iCacheSearchKey->Context().SetSourceL( aContextSource );
+    TInt index = KErrNone;
+    if( iContextCache.FindInOrder( iCacheSearchKey, index,
+        *iCacheOrder ) == KErrNone )
+        {
+        // index points to the matching object
+        if( index >= 0 && index < iContextCache.Count() )
+            {
+            User::LeaveIfError( DoReadSecurityCheck(
+                *iContextCache[index],
+                aClientThread ) );
+            return &iContextCache[index]->Context();
+            }
+        else
+            {
+            return NULL;
+            }
+        }
+    else    // == KErrNotFound
+        {   // index points to "the place to be"
+        return NULL;
+        }
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::SubscriptionAddedL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::SubscriptionAddedL(
+    CCFContextSubscriptionImpl& aSubscription,
+    RThread& aClientThread )
+    {
+    FUNC_LOG;
+
+    TInt count = iContextCache.Count();
+    CCFCacheElement* element = NULL;
+    for( TInt i = 0; i < count; i++ )
+        {
+        element = iContextCache[i];
+        if( aSubscription.Matches( element->Context().Type(),
+            element->Context().Source() ) )
+            {
+            TInt err = DoReadSecurityCheck( *element, aClientThread );
+            if (err == KErrNone)
+            	{
+            	element->AddSubscriptionL( aSubscription );
+            	}
+            else
+            	{
+            	aSubscription.SubscriptionListener().HandleContextSubscriptionError( err,
+            		element->Context().Source(),
+            		element->Context().Type() );
+            	}
+            }
+        }
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::SubscriptionRemoved
+//-----------------------------------------------------------------------------
+//
+TBool CCFContextManager::SubscriptionRemoved(
+    CCFContextSubscriptionImpl& aSubscription)
+    {
+    FUNC_LOG;
+
+    TBool cleanupElement( EFalse );
+    for( TInt i = 0; i < iContextCache.Count(); i++ )
+        {
+        TInt j = iContextCache[ i ]->Subscriptions().Count() - 1;
+        for( ; j >= 0; j-- )
+            {
+            if( &aSubscription == iContextCache[ i ]->Subscriptions()[ j ] )
+                {
+                CCFCacheElement* cacheElement = iContextCache[ i ];
+                if ( iPublishingForCacheElement
+                    && ( iPublishingForCacheElement == cacheElement ) )
+                    {
+                    cleanupElement = ETrue;
+                    cacheElement->NullifySubscription( j );
+                    TInt err = iCleanupCacheElements.InsertInAddressOrder(
+                            cacheElement );
+                    if ( err == KErrAlreadyExists )
+                        {
+                        err = KErrNone;
+                        }
+                    ERROR( err, "CCFContextManager::SubscriptionRemoved - Adding cache element to cleanup array failed!" );
+                    }
+                else
+                    {
+                    cacheElement->RemoveSubscription( j );
+                    }
+                }
+            }
+        }
+
+    return cleanupElement;
+    }
+
+
+//----------------------------------------------------------------------------
+// CCFContextManager::DefineContextL
+//----------------------------------------------------------------------------
+//
+void CCFContextManager::DefineContextL( const TDesC& aContextSource,
+    const TDesC& aContextType,
+    const TSecurityPolicy& aReadSecurityPolicy,
+    const TSecurityPolicy& aWriteSecurityPolicy )
+    {
+    FUNC_LOG;
+
+    RThread thread;
+    CleanupClosePushL( thread );
+
+    DefineContextL( aContextSource, aContextType, aReadSecurityPolicy,
+    		aWriteSecurityPolicy, NULL, thread.SecureId() );
+
+    CleanupStack::PopAndDestroy( );
+    }
+
+
+//----------------------------------------------------------------------------
+// CCFContextManager::DefineContextL
+//----------------------------------------------------------------------------
+//
+void CCFContextManager::DefineContextL( const TDesC& aContextSource,
+    const TDesC& aContextType,
+    const TSecurityPolicy& aReadSecurityPolicy,
+    const TSecurityPolicy& aWriteSecurityPolicy,
+    MCFContextSource* aContextPublisher,
+    const TUid& aPublisherUid )
+    {
+    FUNC_LOG;
+
+    // Prepare and find context
+    iCacheSearchKey->Context().SetSourceL( aContextSource );
+    iCacheSearchKey->Context().SetTypeL( aContextType );
+    iCacheSearchKey->Context().SetValueL( KNullDesC );
+    iCacheSearchKey->SetReadSecurityPolicy( aReadSecurityPolicy );
+    iCacheSearchKey->SetWriteSecurityPolicy( aWriteSecurityPolicy );
+    iCacheSearchKey->SetContextPublisher( aContextPublisher, aPublisherUid );
+
+    TInt index = KErrNone;
+    TInt searchError = iContextCache.FindInOrder( iCacheSearchKey,
+        index,
+        *iCacheOrder );
+
+    if ( searchError != KErrNone )
+        {
+        // New context type
+        User::LeaveIfError(
+            iContextCache.Insert( iCacheSearchKey, index ) );
+        CacheElementAddedL( *iCacheSearchKey );
+        iCacheSearchKey = NULL;
+        iCacheSearchKey = CCFCacheElement::NewL();
+
+        // Signalling new context type
+        iPreviousContext->SetSourceL( KNullDesC );
+        iPreviousContext->SetTypeL( KNullDesC );
+
+        INFO_2( "New context defined: [%S: %S]",
+            &aContextSource,
+            &aContextType );
+        }
+    else
+        {
+        TInt err = KErrNone;
+        CCFCacheElement* cacheElement = iContextCache[index];
+        if( cacheElement->PublisherUid() == aPublisherUid )
+            {
+            if( RedefineAllowed( *cacheElement, aContextPublisher, aPublisherUid ) )
+                {
+                cacheElement->SetContextPublisher( aContextPublisher,
+                    aPublisherUid );
+                INFO_3( "Context [%S: %S] redefined by client [%x]",
+                    &aContextSource, &aContextType, aPublisherUid.iUid );
+                }
+            else
+                {
+                err = KErrAlreadyExists;
+                }
+            }
+        else
+            {
+            err = KErrAlreadyExists;
+            }
+
+        ERROR_2( err, "Context already defined: [%S: %S]",
+            &aContextSource,
+            &aContextType );
+        User::LeaveIfError( err );
+        }
+    }
+
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::GetReadSecurityPolicyL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::GetReadSecurityPolicyL( const TDesC& aContextSource,
+            const TDesC& aContextType,
+			TSecurityPolicy& aPolicy )
+	{
+	FUNC_LOG;
+
+    TInt count = iContextCache.Count();
+    CCFCacheElement* cacheElement = NULL;
+    for( TInt i = 0; i < count; i++ )
+        {
+        cacheElement = iContextCache[ i ];
+
+        if( cacheElement->Context().Source().Compare( aContextSource ) == 0
+        	&& cacheElement->Context().Type().Compare( aContextType ) == 0 )
+        	{
+			aPolicy = cacheElement->GetReadSecurityPolicy();
+			return;
+        	}
+        }
+
+	ERROR_2( KErrNotFound, "Security Policy for [%S: %S] not found!",
+		&aContextSource, &aContextType );
+	User::Leave( KErrNotFound );
+	}
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::GetWriteSecurityPolicyL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::GetWriteSecurityPolicyL( const TDesC& aContextSource,
+            const TDesC& aContextType,
+			TSecurityPolicy& aPolicy )
+	{
+	FUNC_LOG;
+
+    TInt count = iContextCache.Count();
+    CCFCacheElement* cacheElement = NULL;
+    for( TInt i = 0; i < count; i++ )
+        {
+        cacheElement = iContextCache[ i ];
+
+        if( cacheElement->Context().Source().Compare( aContextSource ) == 0
+        	&& cacheElement->Context().Type().Compare( aContextType ) == 0 )
+        	{
+			aPolicy = cacheElement->GetWriteSecurityPolicy();
+			return;
+        	}
+        }
+
+	ERROR_2( KErrNotFound, "Security Policy for [%S: %S] not found!",
+		&aContextSource, &aContextType );
+	User::Leave( KErrNotFound );
+	}
+
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::DeregisterPublisher
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::DeregisterPublisher( MCFContextSource& aPublisher )
+	{
+    FUNC_LOG;
+
+    for( TInt i = 0; i < iContextCache.Count() ; i++ )
+        {
+        CCFCacheElement* cacheElement = iContextCache[ i ];
+        if( cacheElement->ContextPublisher() == &aPublisher )
+        	{
+			cacheElement->SetContextPublisher( NULL );
+        	}
+        }
+	}
+
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::GetLatestFromCacheL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::GetLatestFromCacheL(
+    RContextObjectArray& aLatestContexts,
+    queryMatchFunction aMatchFunction,
+    const CCFContextQueryImpl& aContextQuery,
+    RThread* aClientThread )
+    {
+    FUNC_LOG;
+
+    TInt count = iContextCache.Count();
+    CCFCacheElement* cacheElement = NULL;
+    for( TInt i = 0; i < count; ++i )
+        {
+        cacheElement = iContextCache[ i ];
+        if( cacheElement->Context().Value().Length()
+            && ( aContextQuery.*aMatchFunction )(
+                cacheElement->Context().Type(),
+                cacheElement->Context().Source() ) )
+            {
+            if( !aClientThread ||
+                DoReadSecurityCheck( *cacheElement, *aClientThread ) == KErrNone )
+                {
+                aLatestContexts.AppendL( &cacheElement->Context() );
+                }
+            }
+        }
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::LogContextCache
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::LogContextCache()
+    {
+#ifdef DEBUG_LOG_CONTEXT_CACHE
+    INFO( "CONTEXT CACHE start:" );
+    TInt cacheIndex;
+    for (cacheIndex = 0; cacheIndex < iContextCache.Count(); ++cacheIndex)
+        {
+        iContextCache[cacheIndex]->DebugPrintContents();
+        }
+    INFO( "CONTEXT CACHE start:" );
+    INFO( "CONTEXT CACHE BY TYPE start:" );
+    for (cacheIndex = 0; cacheIndex < iContextCacheByType.Count() ;
+    ++cacheIndex)
+        {
+        iContextCacheByType[cacheIndex]->DebugPrintContents();
+        }
+    INFO( "CONTEXT CACHE BY TYPE end:" );
+#endif // DEBUG_LOG_CONTEXT_CACHE
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::DoSecurityCheck
+//-----------------------------------------------------------------------------
+//
+TInt CCFContextManager::DoReadSecurityCheck( CCFCacheElement& aContextCache,
+    RThread& aClientThread )
+    {
+    FUNC_LOG;
+
+    // Security check only needed if request is from other process than CF
+    TInt err = KErrNone;
+
+    TBool securityCheckOk =
+        iSecurityChecker->CheckClientSecurity( aClientThread,
+            aContextCache.GetReadSecurityPolicy() );
+
+    if( !securityCheckOk )
+        {
+        // Insuffcient security, indicate client
+        err = KErrAccessDenied;
+        }
+
+    return err;
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::DoSecurityCheck
+//-----------------------------------------------------------------------------
+//
+TInt CCFContextManager::DoWriteSecurityCheck( CCFCacheElement& aContextCache,
+    RThread& aClientThread )
+    {
+    FUNC_LOG;
+
+    // Security check only needed if request is from other process than CF
+    TInt err = KErrNone;
+
+    TBool securityCheckOk =
+        iSecurityChecker->CheckClientSecurity( aClientThread,
+            aContextCache.GetWriteSecurityPolicy() );
+
+    if( !securityCheckOk )
+        {
+        // Insuffcient security, indicate client
+        err = KErrAccessDenied;
+        }
+
+    return err;
+    }
+
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::DoRequestContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::DoRequestContextL( RContextObjectArray& aResultBuffer,
+    CCFContextQuery& aContextQuery,
+    RThread* aClientThread )
+    {
+    FUNC_LOG;
+
+    CCFContextQueryImpl& queryImpl = (CCFContextQueryImpl&) aContextQuery;
+    GetLatestFromCacheL( aResultBuffer,
+        &CCFContextQueryImpl::Matches,
+        queryImpl,
+        aClientThread );
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::SubscribeContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::SubscribeContextL(
+    CCFContextSubscription* aSubscription,
+    MCFContextSubscriptionListener* aListener,
+    RThread& aClientThread )
+    {
+    FUNC_LOG;
+
+	CCFContextSubscriptionImpl* subscriptionImpl =
+        static_cast<CCFContextSubscriptionImpl*>( aSubscription );
+    subscriptionImpl->SetSubscriptionListener( *aListener );
+
+    // Append new subscription into array
+    TInt err = iSubscriptions.Append( subscriptionImpl );
+    if( err != KErrNone )
+        {
+        User::Leave( err );
+        }
+
+    // Notify data manager that new subscription has been added
+    TRAP( err,
+        SubscriptionAddedL( *subscriptionImpl, aClientThread ) );
+    if( err )
+        {
+        iSubscriptions.Remove( iSubscriptions.Count() -1 );
+        User::Leave( err );
+        }
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::RemoveSubscription
+//-----------------------------------------------------------------------------
+//
+TBool CCFContextManager::RemoveSubscription(
+    CCFContextSubscription& aSubscription,
+    MCFContextSubscriptionListener& aListener )
+    {
+    FUNC_LOG;
+
+    TBool cleanupElement( EFalse );
+   	CCFContextSubscriptionImpl* subscriptionImpl =
+   	    static_cast<CCFContextSubscriptionImpl*>( &aSubscription );
+
+    subscriptionImpl->SetSubscriptionListener( aListener );
+    TBool deleteSubscriptionImpl( EFalse );
+
+    TInt i = iSubscriptions.Count() - 1;
+    while ( i >= 0 )
+        {
+        if ( i >= iSubscriptions.Count() )
+            {
+            // Context source has removed subscriptions via synchronous call
+            // e.g. from managers call to source's NoSubscribers() function.
+            i = iSubscriptions.Count() - 1;
+            }
+
+        if ( i < 0 )
+            {
+            INFO( "All subscriptions removed" );
+            break;
+            }
+
+        if ( iSubscriptions[ i ]->IsSame( *subscriptionImpl ) )
+            {
+            CCFContextSubscriptionImpl* subscription = iSubscriptions[ i ];
+            iSubscriptions.Remove( i );
+            INFO_2( "CCFContextManager::RemoveSubscription - Subscription [%S: %S] removed",
+                    &subscription->ContextSource(),
+                    &subscription->ContextType() );
+            if ( SubscriptionRemoved( *subscription ) )
+                {
+                cleanupElement = ETrue;
+                }
+            if ( subscription != subscriptionImpl )
+                {
+                delete subscription;
+                }
+            else
+                {
+                // Delay deleting when the same subscription instance is used
+                // internally for both subscribe and unsubscribe.
+                deleteSubscriptionImpl = ETrue;
+                }
+            }
+        --i;
+        }
+
+    if ( deleteSubscriptionImpl )
+        {
+        delete subscriptionImpl;
+        }
+
+    return cleanupElement;
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::RemoveSubscription
+//-----------------------------------------------------------------------------
+//
+TBool CCFContextManager::RemoveSubscriptions(
+    MCFContextSubscriptionListener* aListener)
+    {
+    FUNC_LOG;
+
+    TBool cleanupElement( EFalse );
+
+    TInt i = iSubscriptions.Count() - 1;
+    while ( i >= 0 )
+        {
+        if ( i >= iSubscriptions.Count() )
+            {
+            // Context source has removed subscriptions via synchronous call
+            // e.g. from managers call to source's NoSubscribers() function.
+            i = iSubscriptions.Count() - 1;
+            }
+
+        if ( i < 0 )
+            {
+            INFO( "All subscriptions removed" );
+            break;
+            }
+
+        CCFContextSubscriptionImpl* subscription = iSubscriptions[ i ];
+        if ( &( subscription->SubscriptionListener() ) == aListener )
+            {
+            iSubscriptions.Remove( i );
+            if ( SubscriptionRemoved( *subscription ) )
+                {
+                cleanupElement = ETrue;
+                }
+            delete subscription;
+            subscription = NULL;
+            }
+        --i;
+        }
+
+    return cleanupElement;
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::CleanupCacheElementSubscriptions
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::CleanupCacheElementSubscriptions()
+    {
+    FUNC_LOG;
+
+    for ( TInt i = 0; i < iCleanupCacheElements.Count(); ++i )
+        {
+        CCFCacheElement* element = iCleanupCacheElements[ i ];
+        element->RemoveNullSubscriptions();
+        }
+    iCleanupCacheElements.Reset();
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::CacheElementAddedL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::CacheElementAddedL(
+    CCFCacheElement& aCacheElement )
+    {
+    FUNC_LOG;
+
+    TInt count = iSubscriptions.Count();
+    CCFContextSubscriptionImpl* subscription = NULL;
+    for( TInt i = 0; i < count; i++ )
+        {
+        subscription = iSubscriptions[i];
+        if( subscription->Matches( aCacheElement.Context().Type(),
+            aCacheElement.Context().Source() ) )
+            {
+            // Check security
+            RThread thread;
+            TInt err =
+                subscription->SubscriptionListener().Client( thread );
+            if( err == KErrNone )
+                {
+                err = DoReadSecurityCheck( aCacheElement, thread );
+                if( err == KErrNone )
+                    {
+                    aCacheElement.AddSubscriptionL( *subscription );
+                    }
+                else
+                    {
+                    subscription->SubscriptionListener().HandleContextSubscriptionError(
+                        err,
+            			aCacheElement.Context().Source(),
+            			aCacheElement.Context().Type() );
+                    }
+                }
+            else
+                {
+                subscription->SubscriptionListener().HandleContextSubscriptionError(
+                    err,
+            		aCacheElement.Context().Source(),
+            		aCacheElement.Context().Type() );
+                }
+            thread.Close();
+            }
+        }
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::ValidatePublishContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::ValidatePublishContextL( CCFContextObject& aContext,
+    RThread& aClientThread )
+    {
+    FUNC_LOG;
+
+    // Define context
+    iCacheSearchKey->Context().CopyL( aContext );
+    CCFCacheElement* currentCacheElement = iCacheSearchKey;
+    TInt index = KErrNone;
+    TInt searchError = iContextCache.FindInOrder( iCacheSearchKey,
+        index,
+        *iCacheOrder);
+
+    // Both source and type must match.
+    // Otherwise context has not been defined and will lead to error.
+    if( searchError == KErrNone )
+        {
+        if( index >= 0 && index < iContextCache.Count() )
+            {
+            // index and indexByType points to the matching cache elements
+            currentCacheElement = iContextCache[index];
+            }
+        else
+            {
+            // index not found -> leave
+            ERROR_GEN( "Context cache element not found from cache list" );
+            User::Leave( KErrNotFound );
+            }
+
+        // Perform security check
+        TInt err = DoWriteSecurityCheck( *currentCacheElement, aClientThread );
+        ERROR_2( err, "Security check failed: [%S: %S]",
+             &aContext.Source(),
+             &aContext.Type() );
+        User::LeaveIfError( err );
+        }
+    else
+        {
+        // Indicate client that specified context cannot be found
+        ERROR_2( KErrNotFound, "Published context not found: [%S: %S]",
+            &aContext.Source(),
+            &aContext.Type() );
+        User::Leave( KErrNotFound );
+        }
+    }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::DoPublishContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::DoPublishContextL( CCFContextObject& aContext,
+    CCFContextDataObject* aData )
+    {
+    FUNC_LOG;
+
+    // Define context
+    aContext.SetTimestampToHomeTime();
+    iCacheSearchKey->Context().CopyL( aContext );
+    CCFCacheElement* currentCacheElement = iCacheSearchKey;
+    TBool valueChanged = EFalse;
+    TInt index = KErrNone;
+    TInt searchError = iContextCache.FindInOrder( iCacheSearchKey,
+        index,
+        *iCacheOrder);
+
+    // Both source and type must match.
+    // Otherwise context has not been defined and will lead to error.
+    if( searchError == KErrNone )
+        {
+        if( index >= 0 && index < iContextCache.Count() )
+            {
+            // index and indexByType points to the matching cache elements
+            currentCacheElement = iContextCache[ index ];
+            }
+        else
+            {
+            // index not found -> leave
+            ERROR( KErrNotFound, "Context cache element not found from cache list" );
+            User::Leave( KErrNotFound );
+            }
+
+        // store previous values
+        iPreviousContext->CopyL( currentCacheElement->Context() );
+
+        // Check if we have to update cache and indicate subscribers
+        if( currentCacheElement->Context().Value() != aContext.Value() )
+            {
+            // Update context
+            currentCacheElement->Context().CopyL( aContext );
+            valueChanged = ETrue;
+            }
+
+        LogContextCache();
+
+        // Let subscriptions do the indication if needed
+        iPublishingForCacheElement = currentCacheElement;
+        const RPointerArray< CCFContextSubscriptionImpl >& subscriptions =
+            currentCacheElement->Subscriptions();
+        TInt count = subscriptions.Count();
+        CCFContextSubscriptionImpl* subscription = NULL;
+        for( TInt i = 0 ; i < count; i++ )
+            {
+            subscription = subscriptions[ i ];
+            if( subscription )
+                {
+                if( aData && subscription->DataObjectEnabled() )
+                    {
+                    subscription->EvaluateContextChangeL( aContext,
+                        *aData,
+                        valueChanged );
+                    }
+                else
+                    {
+                    subscription->EvaluateContextChangeL( aContext,
+                        *iPreviousContext,
+                        valueChanged );
+                    }
+                }
+            }
+        iPublishingForCacheElement = NULL;
+
+        INFO_3( "Published context: [%S: %S: %S]",
+            &aContext.Source(),
+            &aContext.Type(),
+            &aContext.Value() );
+        if( aData )
+            {
+            INFO_1( "Published data object: [0x%x]", aData->Uid() );
+            }
+        }
+    else
+        {
+        // Indicate client that specified context cannot be found
+        ERROR_2( KErrNotFound, "Published context not found: [%S: %S]",
+            &aContext.Source(),
+            &aContext.Type() );
+        User::Leave( KErrNotFound );
+        }
+    }
+
+//------------------------------------------------------------------------------
+// CCFContextManager::RedefineAllowed
+//------------------------------------------------------------------------------
+//
+TBool CCFContextManager::RedefineAllowed( CCFCacheElement& aElement,
+    const MCFContextSource* aSource,
+    const TUid& aUid ) const
+    {
+    FUNC_LOG;
+
+    TBool allowed = EFalse;
+
+    // Redefine is allowed:
+    // - Same client session from the same client process
+    if( aElement.ContextPublisher() == aSource &&
+        aElement.PublisherUid() == aUid )
+        {
+        allowed = ETrue;
+        }
+
+    // - The owner is NULL and the client process is the same
+    else if( !aElement.ContextPublisher() &&
+        aElement.PublisherUid() == aUid )
+        {
+        allowed = ETrue;
+        }
+
+    // - Owner is NULL and the redefine is done by context source plug-in
+    else if( !aElement.ContextPublisher() &&
+        KCFServerSid == aUid )
+        {
+        allowed = ETrue;
+        }
+
+    return allowed;
+    }
+
+// End of file
+