--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/client/src/ncdsubscriptionmanagerproxy.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,570 @@
+/*
+* 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: Contains CNcdSubscriptionManagerProxy class implementation
+*
+*/
+
+
+#include "ncdsubscriptionmanagerproxy.h"
+#include "ncdsubscriptiongroupproxy.h"
+#include "ncdsubscriptionproxy.h"
+#include "ncdsubscriptionoperationproxy.h"
+#include "ncdoperationimpl.h"
+#include "ncddownloadoperationproxy.h"
+#include "ncdoperationmanagerproxy.h"
+#include "ncdoperationdatatypes.h"
+#include "catalogsclientserver.h"
+#include "ncdnodeidentifier.h"
+#include "ncdnodefunctionids.h"
+#include "ncdnodeclassids.h"
+#include "catalogsinterfaceidentifier.h"
+#include "catalogsutils.h"
+#include "ncdutils.h"
+#include "catalogsconstants.h"
+#include "ncdsubscriptionmanagerlistener.h"
+
+#include "catalogsdebug.h"
+
+// ======== PUBLIC MEMBER FUNCTIONS ========
+
+CNcdSubscriptionManagerProxy::CNcdSubscriptionManagerProxy(
+ MCatalogsClientServer& aSession,
+ TInt aHandle,
+ CCatalogsInterfaceBase* aParent,
+ CNcdOperationManagerProxy& aOperationManager )
+ : CNcdInterfaceBaseProxy( aSession, aHandle, aParent ),
+ iOperationManager( aOperationManager )
+ {
+ }
+
+
+void CNcdSubscriptionManagerProxy::ConstructL()
+ {
+ DLTRACEIN((""));
+
+ // Register the interface
+ MNcdSubscriptionManager* interface( this );
+ AddInterfaceL( CCatalogsInterfaceIdentifier::NewL(
+ interface, this,
+ MNcdSubscriptionManager::KInterfaceUid ) );
+
+ // Create listener.
+ iListener = CNcdSubscriptionManagerListener::NewL( *this );
+
+ iInputBuf.CreateL( 1 );
+ iOutputBuf.CreateL( 1 );
+
+
+ // Is it ok if internalization fails here?
+ // Earlier comment: Do not let the internalization leave here.
+ // This object may be reinternalized later.
+ InternalizeL();
+
+ // Send an asynchronous message to server side subscription manager to be notified
+ // when subscription states are changed in server side.
+ ClientServerSession().SendAsync(
+ NcdNodeFunctionIds::ENcdListenerEnrollment,
+ iOutputBuf,
+ iInputBuf,
+ Handle(),
+ iListener->iStatus );
+
+ iListener->Activate();
+
+ DLTRACEOUT((""));
+ }
+
+
+CNcdSubscriptionManagerProxy* CNcdSubscriptionManagerProxy::NewL(
+ MCatalogsClientServer& aSession,
+ TInt aHandle,
+ CCatalogsInterfaceBase* aParent,
+ CNcdOperationManagerProxy& aOperationManager )
+ {
+ CNcdSubscriptionManagerProxy* self =
+ CNcdSubscriptionManagerProxy::NewLC( aSession,
+ aHandle,
+ aParent,
+ aOperationManager );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+CNcdSubscriptionManagerProxy* CNcdSubscriptionManagerProxy::NewLC(
+ MCatalogsClientServer& aSession,
+ TInt aHandle,
+ CCatalogsInterfaceBase* aParent,
+ CNcdOperationManagerProxy& aOperationManager )
+ {
+ CNcdSubscriptionManagerProxy* self =
+ new( ELeave ) CNcdSubscriptionManagerProxy( aSession,
+ aHandle,
+ aParent,
+ aOperationManager );
+ // Using PushL because the object does not have any references yet
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+
+CNcdSubscriptionManagerProxy::~CNcdSubscriptionManagerProxy()
+ {
+ // Remove interfaces implemented by this class from the interface list.
+ // So, the interface list is up to date when this class object is deleted.
+ RemoveInterface( MNcdSubscriptionManager::KInterfaceUid );
+
+ iSubscriptionGroups.ResetAndDestroy();
+
+ delete iListener;
+ iInputBuf.Close();
+ iOutputBuf.Close();
+ }
+
+
+void CNcdSubscriptionManagerProxy::SetNodeManager(
+ CNcdNodeManagerProxy* aManager )
+ {
+ // Not owned so no deletion needed for possible previous object
+ iNodeManager = aManager;
+ }
+
+void CNcdSubscriptionManagerProxy::InternalizeL()
+ {
+ DLTRACEIN((""));
+
+ // Request the subscription group identifiers from server.
+ RPointerArray<CNcdKeyValuePair> groupIds = SubscriptionGroupIdentifiersL();
+ CleanupResetAndDestroyPushL( groupIds );
+
+ DLINFO(("Amount of ids received: %d", groupIds.Count() ));
+
+ // Release the subscription groups that don't exist in server side.
+ DeleteMissingSubscriptionGroups( groupIds );
+
+ // Reinternalize existing subscriptiongroup.
+ InternalizeSubscriptionGroupsL();
+
+ // Remove the subscription groups from the array which are up to date currently.
+ for ( TInt i = groupIds.Count() - 1; i >= 0; i-- )
+ {
+ if ( SubscriptionGroup( groupIds[i]->Value(), groupIds[i]->Key() ) != NULL )
+ {
+ delete groupIds[i];
+ groupIds.Remove( i );
+ }
+ }
+
+ // Request handles to the new subscription groups
+ CBufBase* buf = CBufFlat::NewL( KBufExpandSize );
+ CleanupStack::PushL( buf );
+
+ RBufWriteStream writeStream( *buf );
+ CleanupClosePushL( writeStream );
+
+ writeStream.WriteInt32L( groupIds.Count() );
+ for ( TInt i = 0; i < groupIds.Count(); i++ )
+ {
+ groupIds[i]->ExternalizeL( writeStream );
+ }
+
+ CleanupStack::PopAndDestroy( &writeStream );
+
+
+ HBufC8* dataToSend = HBufC8::NewL( buf->Size() );
+ dataToSend->Des().Copy( buf->Ptr( 0 ) );
+ CleanupStack::PopAndDestroy( buf );
+ CleanupStack::PushL( dataToSend );
+
+ HBufC8* data( NULL );
+
+ DLINFO(("Request buffer: %S", dataToSend ));
+
+ // Because we do not know the exact size of the data, use
+ // the alloc method, which creates the buffer of the right size
+ // and sets the pointer to point to the created buffer.
+ // Get all the data that is necessary to internalize this object
+ // from the server side.
+ User::LeaveIfError(
+ ClientServerSession().
+ SendSyncAlloc( NcdNodeFunctionIds::ENcdInternalize,
+ *dataToSend,
+ data,
+ Handle(),
+ 0 ) );
+
+ if ( data == NULL )
+ {
+ DLERROR((""));
+ User::Leave( KErrNotFound );
+ }
+
+ CleanupStack::PopAndDestroy( dataToSend );
+ CleanupStack::PushL( data );
+
+ // Read the data from the stream and insert it to the memeber variables
+ RDesReadStream stream( *data );
+ CleanupClosePushL( stream );
+
+ TRAPD( internalizeError, InternalizeDataL( stream ) );
+ if ( internalizeError != KErrNone )
+ {
+ // Should check that no handles are left to the
+ // stream. If there are, release messages should
+ // be sent to the server side with those handles.
+ iSubscriptionGroups.ResetAndDestroy();
+ User::Leave( internalizeError );
+ }
+
+ // Closes the stream
+ CleanupStack::PopAndDestroy( &stream );
+ CleanupStack::PopAndDestroy( data );
+ CleanupStack::PopAndDestroy( &groupIds );
+
+ DLTRACEOUT((""));
+ }
+
+
+TBool CNcdSubscriptionManagerProxy::ActiveSubscriptionExists(
+ const TDesC& aEntityId,
+ const TDesC& aNamespace,
+ const TDesC& aPurchaseOptionId )
+ {
+ DLTRACEIN((""));
+ CNcdSubscriptionProxy* searchedSubscription( NULL );
+ searchedSubscription = Subscription( aEntityId,
+ aNamespace,
+ aPurchaseOptionId );
+
+ if ( searchedSubscription != NULL )
+ {
+ if ( searchedSubscription->SubscriptionStatus() ==
+ MNcdSubscription::ESubscriptionActive )
+ {
+ DLTRACEOUT(("Return ETrue"));
+ return ETrue;
+ }
+ }
+ DLTRACEOUT(("Return EFalse"));
+ return EFalse;
+ }
+
+CNcdSubscriptionProxy* CNcdSubscriptionManagerProxy::Subscription(
+ const TDesC& aEntityId,
+ const TDesC& aNamespace,
+ const TDesC& aPurchaseOptionId )
+ {
+ DLTRACEIN((""));
+ CNcdSubscriptionProxy* resultSubscription( NULL );
+
+ // First find the subscription group...
+ CNcdSubscriptionGroupProxy* group( NULL );
+ group = SubscriptionGroup( aEntityId, aNamespace );
+
+ if ( group != NULL )
+ {
+ // then subscription...
+ resultSubscription = group->Subscription( aPurchaseOptionId );
+ }
+
+ DLTRACEOUT((""));
+ return resultSubscription;
+ }
+
+void CNcdSubscriptionManagerProxy::SubscriptionsChangedL()
+ {
+ DLTRACEIN((""));
+
+ // Send new listener enrollment message to server side.
+ ClientServerSession().SendAsync(
+ NcdNodeFunctionIds::ENcdListenerEnrollment,
+ iOutputBuf,
+ iInputBuf,
+ Handle(),
+ iListener->iStatus );
+ iListener->Activate();
+
+ // Internalize the data from server.
+ InternalizeL();
+ }
+
+
+
+// MNcdSubscriptionManager functions
+
+
+
+// ---------------------------------------------------------------------------
+// Subscriptions are now under subscription groups so they are not
+// kept in one large array.
+// Benefit from the one large array would be that the returning of
+// all subscriptions in this function would be easy but because
+// the array would have to be updated or remade after every
+// update from server (which is always before this function) it seems
+// that keeping up the large array does not benefit us. Atleast
+// not in this function.
+// ---------------------------------------------------------------------------
+//
+RCatalogsArray<MNcdSubscription>
+ CNcdSubscriptionManagerProxy::SubscriptionsL() const
+ {
+ DLTRACEIN(( "" ));
+
+ // When ui asks for subscriptions it does it in the
+ // management view so the ui should update the subscriptions
+ // from the server before this function. Update is not done here.
+
+ // Let's make one array out of the subscriptions
+ RCatalogsArray<MNcdSubscription> subscriptions;
+
+ // in case of leave, destroy its contents (release)
+ CleanupResetAndDestroyPushL( subscriptions );
+
+
+ TInt groupCount( iSubscriptionGroups.Count() );
+ TInt groupIndexer( 0 );
+
+ DLINFO(( "Coming to while" ));
+ while ( groupIndexer < groupCount )
+ {
+ // through all groups
+ const RPointerArray<CNcdSubscriptionProxy>& subscriptionsOfGroup
+ = iSubscriptionGroups[groupIndexer]->Subscriptions();
+
+ TInt subscriptionCount( subscriptionsOfGroup.Count() );
+ TInt subscriptionIndexer( 0 );
+
+ DLINFO(( "Coming to while2" ));
+ while ( subscriptionIndexer < subscriptionCount )
+ {
+ // through all subscriptions of group
+ subscriptions.AppendL(
+ subscriptionsOfGroup[subscriptionIndexer] );
+ subscriptionsOfGroup[subscriptionIndexer]->AddRef();
+ ++subscriptionIndexer;
+ }
+
+ ++groupIndexer;
+ }
+ CleanupStack::Pop( &subscriptions );
+
+ DLTRACEOUT(( "" ));
+ return subscriptions;
+ }
+
+
+MNcdSubscriptionOperation*
+ CNcdSubscriptionManagerProxy::RefreshSubscriptionsL(
+ MNcdSubscriptionOperationObserver& aObserver )
+ {
+ DLTRACEIN((""));
+
+ CNcdSubscriptionOperationProxy* operation( NULL );
+
+ operation =
+ iOperationManager.CreateSubscriptionRefreshOperationL( aObserver );
+
+ DLTRACEOUT((""));
+
+ return operation;
+ }
+
+
+
+// Other functions
+
+CNcdOperationManagerProxy&
+ CNcdSubscriptionManagerProxy::OperationManager() const
+ {
+ return iOperationManager;
+ }
+
+
+
+void CNcdSubscriptionManagerProxy::InternalizeDataL( RReadStream& aStream )
+ {
+ DLTRACEIN((""));
+
+ TInt handleAmount( 0 );
+ handleAmount = aStream.ReadInt32L();
+
+ DLTRACE(( "Amount of subscriptiongroup handles received: %d",
+ handleAmount ));
+
+ TInt tmpProxyHandle( -1 ); // handle of a proxy read from stream
+
+ // temporary pointer to subscription group that is going to be
+ // added to subscriptiongroups-array
+ CNcdSubscriptionGroupProxy* tmpSubscriptionGroup( NULL );
+
+
+ // In error handling, objects with received handles
+ // should be released from the server side session
+ // if proxies for them cannot be created.
+
+ TInt handleIndex( 0 );
+ while ( handleIndex < handleAmount )
+ {
+ tmpProxyHandle = aStream.ReadInt32L();
+
+ DLTRACE(( "Received subscriptiongroup handle: %i",
+ tmpProxyHandle ));
+
+ tmpSubscriptionGroup = CNcdSubscriptionGroupProxy::NewL(
+ ClientServerSession(),
+ tmpProxyHandle,
+ OperationManager(),
+ *iNodeManager );
+
+ TRAPD( addError, iSubscriptionGroups.AppendL( tmpSubscriptionGroup ) );
+ if ( addError != KErrNone )
+ {
+ delete tmpSubscriptionGroup;
+ User::Leave( addError );
+ }
+
+ ++handleIndex;
+ }
+
+ DLTRACEOUT((""));
+ }
+
+RPointerArray<CNcdKeyValuePair> CNcdSubscriptionManagerProxy::SubscriptionGroupIdentifiersL() const
+ {
+ DLTRACEIN((""));
+
+ HBufC8* data( NULL );
+
+ // Because we do not know the exact size of the data, use
+ // the alloc method, which creates the buffer of the right size
+ // and sets the pointer to point to the created buffer.
+ User::LeaveIfError(
+ ClientServerSession().
+ SendSyncAlloc( NcdNodeFunctionIds::ENcdSubscriptionGroupIdentifiers,
+ KNullDesC8,
+ data,
+ Handle(),
+ 0 ) );
+
+ if ( data == NULL )
+ {
+ DLERROR((""));
+ User::Leave( KErrNotFound );
+ }
+
+ CleanupStack::PushL( data );
+
+ // Read the data from the stream and insert it to the memeber variables
+ RDesReadStream stream( *data );
+ CleanupClosePushL( stream );
+
+ TInt32 identifierCount = stream.ReadInt32L();
+ RPointerArray<CNcdKeyValuePair> identifiers;
+ CleanupResetAndDestroyPushL( identifiers );
+ identifiers.ReserveL( identifierCount );
+ for ( TInt i = 0 ; i < identifierCount; i++ )
+ {
+ CNcdKeyValuePair* pair = CNcdKeyValuePair::NewL( stream );
+ TInt err = identifiers.Append( pair );
+ // Error should not be possible since there should be enough room to append.
+ DASSERT( err == KErrNone );
+ }
+
+ CleanupStack::Pop( &identifiers );
+ CleanupStack::PopAndDestroy( &stream );
+ CleanupStack::PopAndDestroy( data );
+
+ return identifiers;
+ }
+
+void CNcdSubscriptionManagerProxy::DeleteMissingSubscriptionGroups(
+ const RPointerArray<CNcdKeyValuePair>& aGroupIdentifiers )
+ {
+ DLTRACEIN((""));
+
+ for ( TInt i = iSubscriptionGroups.Count() - 1; i >= 0; i-- )
+ {
+ const TDesC& nameSpace = iSubscriptionGroups[i]->Namespace();
+ const TDesC& entityId = iSubscriptionGroups[i]->EntityId();
+
+ TBool found = EFalse;
+ for ( TInt idIndexer = 0; idIndexer < aGroupIdentifiers.Count(); idIndexer++ )
+ {
+ if ( aGroupIdentifiers[idIndexer]->Key() == nameSpace &&
+ aGroupIdentifiers[idIndexer]->Value() == entityId )
+ {
+ found = ETrue;
+ break;
+ }
+ }
+
+ if ( !found )
+ {
+ delete iSubscriptionGroups[i];
+ iSubscriptionGroups.Remove( i );
+ }
+ }
+ }
+
+void CNcdSubscriptionManagerProxy::InternalizeSubscriptionGroupsL() const
+ {
+ DLTRACEIN((""));
+ for ( TInt i = 0; i < iSubscriptionGroups.Count(); i++ )
+ {
+ iSubscriptionGroups[i]->InternalizeL();
+ }
+ }
+
+CNcdSubscriptionGroupProxy* CNcdSubscriptionManagerProxy::SubscriptionGroup(
+ const TDesC& aEntityId,
+ const TDesC& aNamespace )
+ {
+ DLTRACEIN((""));
+ // Search for the subscription group
+
+ TInt groupCount( iSubscriptionGroups.Count() );
+ TInt groupIndexer( 0 );
+ while ( groupIndexer < groupCount )
+ {
+ const TDesC& groupsEntityId =
+ iSubscriptionGroups[groupIndexer]->EntityId();
+ const TDesC& groupsNamespace =
+ iSubscriptionGroups[groupIndexer]->Namespace();
+
+ DLINFO(( _L("Searched entityid: %S, now entityid: %S"),
+ &aEntityId,
+ &groupsEntityId ));
+
+ if ( aEntityId == groupsEntityId )
+ {
+
+ DLINFO(( _L("Searched namespace: %S, now namespace: %S"),
+ &aNamespace,
+ &groupsNamespace ));
+
+ if ( aNamespace == groupsNamespace )
+ {
+ DLTRACEOUT(("Found."));
+ return iSubscriptionGroups[groupIndexer];
+ }
+
+ }
+
+ ++groupIndexer;
+ }
+
+ DLTRACEOUT(("Not found."));
+ return NULL;
+ }
+