sl@0: /*
sl@0: * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: * All rights reserved.
sl@0: * This component and the accompanying materials are made available
sl@0: * under the terms of the License "Eclipse Public License v1.0"
sl@0: * which accompanies this distribution, and is available
sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: *
sl@0: * Initial Contributors:
sl@0: * Nokia Corporation - initial contribution.
sl@0: *
sl@0: * Contributors:
sl@0: *
sl@0: * Description: 
sl@0: * Implements the UPS database handle manager.	See class and function
sl@0: * definitions for more information.
sl@0: *
sl@0: */
sl@0: 
sl@0: 
sl@0: /**
sl@0:  @file
sl@0: */
sl@0: #include <f32file.h>
sl@0: #include "upscommon.h"
sl@0: #include "policycache.h"
sl@0: #include "upspolicycachehandle.h"
sl@0: 
sl@0: namespace UserPromptService
sl@0: {
sl@0: 
sl@0: NONSHARABLE_CLASS(CPolicyCacheContainer) : public CBase
sl@0: 	{
sl@0: public:
sl@0: 	static CPolicyCacheContainer *NewL(RFs &aFs);
sl@0: 
sl@0: 	void IncrementReferenceCount();
sl@0: 	void DecrementReferenceCount();
sl@0: 	inline CPolicyCache *PolicyCache();
sl@0: 
sl@0: 	TInt ReferenceCount() const;
sl@0: 
sl@0: 	void NotifyOnRef1(TRequestStatus &aStatus);
sl@0: 	void CancelNotifyOnRef1();
sl@0: 
sl@0: private:
sl@0: 	void ConstructL(RFs &aFs);
sl@0: 	~CPolicyCacheContainer();
sl@0: 	
sl@0: 	TInt iReferenceCount;
sl@0: 	CPolicyCache *iPolicyCache;
sl@0: 	TRequestStatus *iClientRequest;
sl@0: 	};
sl@0: 
sl@0: inline CPolicyCache *CPolicyCacheContainer::PolicyCache()
sl@0: 	{
sl@0: 	ASSERT(iPolicyCache != 0);
sl@0: 	return iPolicyCache;
sl@0: 	}
sl@0: 
sl@0: inline TInt CPolicyCacheContainer::ReferenceCount() const
sl@0: 	{
sl@0: 	return iReferenceCount;
sl@0: 	}
sl@0: 
sl@0: RPolicyCacheCountedHandle::RPolicyCacheCountedHandle(RFs &aFs)
sl@0: 	: iFs(aFs), iContainer(0)
sl@0: 	{
sl@0: 	}
sl@0: 
sl@0: RPolicyCacheCountedHandle::RPolicyCacheCountedHandle(RPolicyCacheCountedHandle &aPolicyCacheManager)
sl@0: 	: iFs(aPolicyCacheManager.iFs), iContainer(0)
sl@0: 	{
sl@0: 	*this = aPolicyCacheManager;
sl@0: 	}
sl@0: 
sl@0: RPolicyCacheCountedHandle &RPolicyCacheCountedHandle::operator=(const RPolicyCacheCountedHandle &aRhs)
sl@0: 	{
sl@0: 	if(this == &aRhs) return *this;
sl@0: 	
sl@0: 	Release();
sl@0: 
sl@0: 	if(aRhs.iContainer)
sl@0: 		{
sl@0: 		iContainer = aRhs.iContainer;
sl@0: 		iContainer->IncrementReferenceCount();
sl@0: 		}
sl@0: 	
sl@0: 	return *this;
sl@0: 	}
sl@0: 
sl@0: RPolicyCacheCountedHandle::~RPolicyCacheCountedHandle()
sl@0: /**
sl@0: 	Destructor - make sure cache container is released.
sl@0: */
sl@0: 	{
sl@0: 	Release();
sl@0: 	}
sl@0: 
sl@0: void RPolicyCacheCountedHandle::OpenL()
sl@0: /**
sl@0: 	Create/Open a new policy cache. If this manager is already opened then the existing cache is
sl@0: 	released first (see Release()).
sl@0: */
sl@0: 	{
sl@0: 	// First release any existing container/policy cache.
sl@0: 	Release();
sl@0: 
sl@0: 	// Now create a new one
sl@0: 	iContainer = CPolicyCacheContainer::NewL(iFs);
sl@0: 	}
sl@0: 
sl@0: void RPolicyCacheCountedHandle::Release()
sl@0: /**
sl@0: 	Release the current policy cache container. If this decreases its reference count to 0, it will be
sl@0: 	deleted.
sl@0: */
sl@0: 	{
sl@0: 	if(iContainer)
sl@0: 		{
sl@0: 		iContainer->DecrementReferenceCount();
sl@0: 		iContainer = 0;
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: TBool RPolicyCacheCountedHandle::IsOpen() const
sl@0: 	{
sl@0: 	return iContainer != 0;
sl@0: 	}
sl@0: 
sl@0: CPolicyCache *RPolicyCacheCountedHandle::operator->()
sl@0: /**
sl@0: 	Returns the CPolicyCache ptr so -> can be used to call policy cache functions.
sl@0: 
sl@0: 	If the class is not already open, then we will attempt to open ourself using OpenL().
sl@0: 
sl@0: 	Note that this operator can leave...
sl@0: */
sl@0: 	{
sl@0: 	if(iContainer == 0)
sl@0: 		{
sl@0: 		OpenL();
sl@0: 		ASSERT(iContainer);
sl@0: 		}
sl@0: 	return iContainer->PolicyCache();
sl@0: 	}
sl@0: 
sl@0: void RPolicyCacheCountedHandle::NotifyOnRef1(TRequestStatus &aStatus)
sl@0: /**
sl@0: 	Register for notifcation when the underlying CPolicyCacheContainer reference
sl@0: 	count reaches 1, presumably when the client holds the only reference.
sl@0: 
sl@0: 	Only one client is allowed to register against a single CPolicyCacheContainer.
sl@0: */
sl@0: 	{
sl@0: 	if((iContainer == 0) || (iContainer->ReferenceCount() <= 1))
sl@0: 		{
sl@0: 		// No container or ref count is 1, so complete now.
sl@0: 		TRequestStatus *rs = &aStatus;
sl@0: 		*rs = KRequestPending;
sl@0: 		User::RequestComplete(rs, KErrNone);
sl@0: 		return;
sl@0: 		}
sl@0: 	iContainer->NotifyOnRef1(aStatus);
sl@0: 	}
sl@0: 
sl@0: void RPolicyCacheCountedHandle::CancelNotifyOnRef1()
sl@0: /**
sl@0: 	Cancel the call to NotifyOnRef1. The request will be completed immediately.
sl@0: */
sl@0: 	{
sl@0: 	if(!iContainer)
sl@0: 		{
sl@0: 		return;
sl@0: 		}
sl@0: 	iContainer->CancelNotifyOnRef1();
sl@0: 	}
sl@0: 
sl@0: CPolicyCacheContainer *CPolicyCacheContainer::NewL(RFs &aFs)
sl@0: /**
sl@0: 	Create a CPolicyCacheContainer containing a CPolicyCache with a reference count of 1.
sl@0: */
sl@0: 	{
sl@0: 	CPolicyCacheContainer *self = new(ELeave) CPolicyCacheContainer();
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL(aFs);
sl@0: 	CleanupStack::Pop(self);
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: void CPolicyCacheContainer::IncrementReferenceCount()
sl@0: /**
sl@0: 	Increment the reference count.
sl@0: */
sl@0: 	{
sl@0: 	ASSERT(iReferenceCount > 0);
sl@0: 	++iReferenceCount;
sl@0: 	}
sl@0: 
sl@0: void CPolicyCacheContainer::DecrementReferenceCount()
sl@0: /**
sl@0: 	Decrement the reference count and delete self if it reaches 0.
sl@0: */
sl@0: 	{
sl@0: 	--iReferenceCount;
sl@0: 	if(iReferenceCount <= 1)
sl@0: 		{
sl@0: 		if(iClientRequest && iClientRequest->Int() == KRequestPending)
sl@0: 			{
sl@0: 			User::RequestComplete(iClientRequest, KErrNone);
sl@0: 			}
sl@0: 		}
sl@0: 
sl@0: 	if(iReferenceCount <= 0)
sl@0: 		{
sl@0: 		delete this;
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: void CPolicyCacheContainer::NotifyOnRef1(TRequestStatus &aStatus)
sl@0: /**
sl@0: 	Register for notifcation when the reference count reduces to 1, presumably 
sl@0: 	when the client holds the only reference.
sl@0: 
sl@0: 	Only one client is allowed to register against a single CPolicyCacheContainer.
sl@0: */
sl@0: 	{
sl@0: 	BULLSEYE_OFF
sl@0: 	if(iClientRequest != 0)
sl@0: 		{
sl@0: 		TRequestStatus *rs = &aStatus;
sl@0: 		*rs = KRequestPending;
sl@0: 		User::RequestComplete(rs, KErrServerBusy);
sl@0: 		return;
sl@0: 		}
sl@0: 	BULLSEYE_RESTORE
sl@0: 
sl@0: 	// Initialise client request
sl@0: 	iClientRequest = &aStatus;
sl@0: 	*iClientRequest = KRequestPending;
sl@0: 
sl@0: 	// Are we already at ref 1?
sl@0: 	if(iReferenceCount <= 1)
sl@0: 		{
sl@0: 		User::RequestComplete(iClientRequest, KErrNone);
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: void CPolicyCacheContainer::CancelNotifyOnRef1()
sl@0: /**
sl@0: 	Cancel the previous call to NotifyOnRef1.
sl@0: */
sl@0: 	{
sl@0: 	if((iClientRequest != 0) && (iClientRequest->Int() == KRequestPending))
sl@0: 		{
sl@0: 		User::RequestComplete(iClientRequest, KErrCancel);
sl@0: 		return;
sl@0: 		}
sl@0: 	}	
sl@0: 
sl@0: void CPolicyCacheContainer::ConstructL(RFs &aFs)
sl@0: 	{
sl@0: 	_LIT(KPolicyDir,"\\private\\10283558\\policies\\");
sl@0: 	iPolicyCache = CPolicyCache::NewL(aFs, KPolicyDir());
sl@0: 	iReferenceCount = 1;
sl@0: 	}
sl@0: 
sl@0: CPolicyCacheContainer::~CPolicyCacheContainer()
sl@0: 	{
sl@0: 	delete iPolicyCache;
sl@0: 	iPolicyCache = 0;
sl@0: 
sl@0: 	if(iClientRequest && iClientRequest->Int() == KRequestPending)
sl@0: 		{
sl@0: 		User::RequestComplete(iClientRequest, KErrNone);
sl@0: 		iClientRequest = 0;
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: } // End of UserPromptService namespace
sl@0: 
sl@0: // End of file
sl@0: