--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/server/src/ncdloadrootnodeoperationimpl.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,1828 @@
+/*
+* 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:
+*
+*/
+
+
+#include <badesca.h>
+#include <s32mem.h>
+
+#include "ncdloadrootnodeoperationimpl.h"
+#include "ncdoperationfunctionids.h"
+#include "catalogsbasemessage.h"
+#include "catalogshttpsession.h"
+#include "catalogshttpoperation.h"
+#include "catalogshttpconfig.h"
+#include "catalogsbigdes.h"
+#include "catalogsaccesspointmanagerimpl.h"
+#include "ncdrequestgenerator.h"
+
+#include "ncdrequestbase.h"
+#include "ncdrequestbrowsesearch.h"
+#include "ncdrequestconfiguration.h"
+#include "ncd_pp_itemref.h"
+#include "ncd_pp_folderref.h"
+#include "ncd_pp_dataentity.h"
+#include "ncd_cp_query.h"
+#include "ncd_cp_queryelement.h"
+#include "ncd_cp_queryoption.h"
+
+#include "ncdprotocolutils.h"
+#include "ncdprotocol.h"
+#include "ncdprotocolimpl.h"
+#include "ncdparser.h"
+#include "ncdnodemanager.h"
+#include "ncdproviderdefines.h"
+#include "ncdnodeidentifier.h"
+#include "ncdnodeclassids.h"
+#include "ncdnodefolder.h"
+#include "ncdrootnode.h"
+#include "ncdbundlefolder.h"
+#include "ncdloadnodeoperationimpl.h"
+#include "ncd_cp_detail.h"
+#include "ncd_cp_clientconfiguration.h"
+#include "ncd_cp_error.h"
+#include "catalogscontext.h"
+#include "ncd_cp_serverdetails.h"
+#include "ncdqueryimpl.h"
+#include "ncdnodelink.h"
+#include "ncd_cp_queryresponseimpl.h"
+#include "catalogsutils.h"
+#include "ncderrors.h"
+#include "ncdconfigurationmanager.h"
+#include "ncdoperationremovehandler.h"
+#include "ncdnodemetadataimpl.h"
+#include "ncdnodeiconimpl.h"
+#include "ncdsessionhandler.h"
+#include "ncd_pp_error.h"
+#include "ncdconfigurationkeys.h"
+#include "ncdutils.h"
+#include "ncdnodeidentifiereditor.h"
+#include "ncdnodeidentifier.h"
+#include "ncdchildentity.h"
+#include "ncdprotocolstrings.h"
+#include "ncdnodeseeninfo.h"
+#include "ncdchildentitymap.h"
+#include "ncdproviderutils.h"
+#include "ncdhttputils.h"
+#include "ncdgeneralmanager.h"
+
+#include "catalogsdebug.h"
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+CNcdLoadRootNodeOperation* CNcdLoadRootNodeOperation::NewL(
+ TInt aClientUid,
+ CNcdGeneralManager& aGeneralManager,
+ MCatalogsHttpSession& aHttpSession,
+ MNcdOperationRemoveHandler* aRemoveHandler,
+ MCatalogsSession& aSession )
+ {
+ CNcdLoadRootNodeOperation* self = CNcdLoadRootNodeOperation::NewLC(
+ aClientUid,
+ aGeneralManager,
+ aHttpSession,
+ aRemoveHandler,
+ aSession );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+CNcdLoadRootNodeOperation* CNcdLoadRootNodeOperation::NewLC(
+ TInt aClientUid,
+ CNcdGeneralManager& aGeneralManager,
+ MCatalogsHttpSession& aHttpSession,
+ MNcdOperationRemoveHandler* aRemoveHandler,
+ MCatalogsSession& aSession )
+ {
+ CNcdLoadRootNodeOperation* self =
+ new( ELeave ) CNcdLoadRootNodeOperation(
+ aClientUid,
+ aGeneralManager,
+ aHttpSession,
+ aRemoveHandler,
+ aSession );
+ CleanupClosePushL( *self );
+ self->ConstructL();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+CNcdLoadRootNodeOperation::~CNcdLoadRootNodeOperation()
+ {
+ DLTRACEIN((""));
+ DASSERT( !iNodeDbLocked );
+ iConfigManager.RemoveObserver( *this );
+
+ iLoadedNodes.ResetAndDestroy();
+
+ DLTRACE(("Delete id, buffer"));
+ delete iRootNodeIdentifier;
+
+ DLTRACE(("Delete parser"));
+ delete iParser;
+ if ( iTransaction )
+ {
+ DLTRACE(("Releasing transaction"));
+ iTransaction->Release();
+ }
+ DLTRACE(("Delete loaded nodes"));
+ iLoadedNodes.ResetAndDestroy();
+
+ DLTRACE(("Closing suboperations"));
+ // Close operations
+ for ( TInt i = 0; i < iSubOps.Count(); ++i )
+ {
+ iSubOps[i]->Close();
+ }
+ DLTRACE(("Suboperations closed"));
+ iSubOps.Reset();
+ iFailedSubOps.Reset();
+ iCompletedSubOps.Reset();
+
+ DLTRACE(("Deleting content sources"));
+ delete iContentSourceMap;
+
+ DLTRACE(("Delete conf response buffer"));
+ delete iConfigResponseBuf;
+
+ if( iConfQuery )
+ {
+ iConfQuery->InternalRelease();
+ }
+
+ iSubOpQuerys.Close();
+
+ delete iServerUri;
+
+ iChildEntityMaps.ResetAndDestroy();
+
+ DLTRACEOUT((""));
+ }
+
+const CNcdNodeIdentifier& CNcdLoadRootNodeOperation::NodeIdentifier() const
+ {
+ return *iRootNodeIdentifier;
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CNcdLoadRootNodeOperation::HandleCancelMessage( MCatalogsBaseMessage* aMessage )
+ {
+ DLTRACEIN((""));
+ Cancel();
+ CNcdBaseOperation::HandleCancelMessage( aMessage );
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CNcdLoadRootNodeOperation::Cancel()
+ {
+ DLTRACEIN( ( "" ) );
+ if ( iTransaction )
+ {
+ iTransaction->Cancel();
+ iTransaction = NULL;
+ }
+
+ if ( iParser )
+ {
+ iParser->CancelParsing();
+ }
+
+ for ( TInt i = 0 ; i < iSubOps.Count() ; i++ )
+ {
+ iSubOps[i]->Cancel();
+ iSubOps[i]->Close();
+ }
+ iSubOps.Reset();
+ if ( iNodeDbLocked )
+ {
+ iNodeManager->UnlockNodeDb( TUid::Uid( iClientUid ) );
+ iNodeDbLocked = EFalse;
+ TRAP_IGNORE( iNodeManager->RevertNodeCacheL( *iRootNodeIdentifier ) );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CNcdLoadRootNodeOperation::HandleHttpEventL(
+ MCatalogsHttpOperation& aOperation,
+ TCatalogsHttpEvent aEvent )
+ {
+ DLTRACEIN((""));
+ DASSERT( &aOperation == iTransaction );
+ DASSERT( aOperation.OperationType() == ECatalogsHttpTransaction );
+
+ TCatalogsTransportProgress progress( iTransaction->Progress() );
+
+ // Are state and id needed?
+ iProgress = TNcdSendableProgress( iRootNodeState,
+ iTransaction->OperationId().Id(), progress.iProgress,
+ progress.iMaxProgress );
+
+ switch( aEvent.iOperationState )
+ {
+ // Handle completed operation
+ case ECatalogsHttpOpCompleted:
+ {
+
+ iTransaction->Release();
+ iTransaction = NULL;
+ // Inform parser that no more data will be sent
+ iParser->EndL();
+ break;
+ }
+
+ // Handle operation in progress
+ case ECatalogsHttpOpInProgress:
+ {
+ if( aEvent.iProgressState == ECatalogsHttpResponseBodyReceived )
+ {
+ // If config response, append the contents to the buffer.
+ if ( iRootNodeState == EReceiveConf )
+ {
+ iConfigResponseBuf->InsertL(
+ iConfigResponseBuf->Size(), aOperation.Body() );
+ }
+
+ // send received data to parser
+ iParser->ParseL( aOperation.Body() );
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+
+TBool CNcdLoadRootNodeOperation::HandleHttpError(
+ MCatalogsHttpOperation& aOperation,
+ TCatalogsHttpError aError )
+ {
+ DLTRACEIN(("Error type: %d, code: %d", aError.iType, aError.iError ));
+ DASSERT( &aOperation == iTransaction );
+
+ aOperation.Release();
+ iTransaction = NULL;
+
+ if ( iMasterServerRedirectionState == ERedirecting )
+ {
+ // Return back to original master server uri.
+ iConfigManager.RemoveObserver( *this );
+ TRAPD(err, iConfigManager.ResetMasterServerAddressL(
+ iPendingMessage->Session().Context() ));
+ if( err != KErrNone )
+ {
+ iError = err;
+ iRootNodeState = EFailed;
+ }
+ else
+ {
+ iMasterServerRedirectionState = EReverted;
+ iRootNodeState = EConfRequest;
+ }
+ }
+ else
+ {
+ iError = aError.iError;
+ iRootNodeState = EFailed;
+ }
+ RunOperation();
+ return ETrue;
+ }
+
+void CNcdLoadRootNodeOperation::ParseError( TInt aErrorCode )
+ {
+ DLTRACEIN(("error:%d", aErrorCode ));
+
+ // Handle error only if not handling an error already
+ // (cancellation of parsing may cause an unnecessary call to this function).
+ if ( iError == KErrNone )
+ {
+ if ( iMasterServerRedirectionState == ERedirecting )
+ {
+ // Return back to original master server uri.
+ iConfigManager.RemoveObserver( *this );
+ TRAPD(err, iConfigManager.ResetMasterServerAddressL(
+ iPendingMessage->Session().Context() ));
+ if( err != KErrNone )
+ {
+ iError = err;
+ iRootNodeState = EFailed;
+ }
+ else
+ {
+ iMasterServerRedirectionState = EReverted;
+ iRootNodeState = EConfRequest;
+ }
+ }
+ else
+ {
+ iRootNodeState = EFailed;
+ iError = aErrorCode;
+ }
+
+ if ( iTransaction )
+ {
+ iTransaction->Cancel();
+ iTransaction = NULL;
+ }
+ if ( iParser )
+ {
+ iParser->CancelParsing();
+ }
+
+ RunOperation();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+void CNcdLoadRootNodeOperation::ParseCompleteL( TInt aError )
+ {
+ DLTRACEIN((_L("error:%d"), aError ));
+
+ if ( iParser )
+ {
+ delete iParser;
+ iParser = NULL;
+ }
+ if ( aError != KErrNone )
+ {
+ DLTRACE(("Parsing error, stop operation!"))
+ iError = aError;
+ iRootNodeState = EFailed;
+ RunOperation();
+ }
+ else
+ {
+ DASSERT( iRootNodeState == EReceiveConf || iRootNodeState == EConfRequest );
+ if ( iConfQuery )
+ {
+ DLTRACE(("Query received, let base op handle it"));
+ iRootNodeState = EConfQuery;
+ // let base op handle the query
+ TRAPD( err, CNcdBaseOperation::QueryReceivedL( iConfQuery ) );
+ if ( err != KErrNone )
+ {
+ iError = err;
+ iRootNodeState = EFailed;
+ RunOperation();
+ }
+ }
+ else if ( iRootNodeState == EConfRequest )
+ {
+ DASSERT( iMasterServerRedirectionState == ERedirecting );
+ RunOperation();
+ }
+ else if ( iContentSourceMap->ContentSourceCount() < 1 &&
+ iContentSourceMap->BundleFolderCount() < 1 )
+ {
+ iError = KNcdErrorNoContentSources;
+ iRootNodeState = EFailed;
+ DLINFO(("No content sources received, stop operation!"))
+ RunOperation();
+ }
+ else
+ {
+ iRootNodeState = EBrowseRequest;
+ RunOperation();
+ }
+ }
+ DLTRACEOUT((""));
+ }
+
+void CNcdLoadRootNodeOperation::ConfigurationBeginL( const TDesC& aVersion,
+ TInt aExpirationDelta )
+ {
+ DLTRACEIN((""));
+ // set expiration delta for root node
+ // No need to set metadata value for root, because it does not have one.
+ iNodeManager->RootNodeL( iRootNodeIdentifier->ClientUid() ).
+ CreateAndSetLinkL().SetValidUntilDelta( aExpirationDelta );
+ // Pass to default observer.
+ DASSERT( iDefaultConfigurationProtocolObserver != NULL );
+ iDefaultConfigurationProtocolObserver->ConfigurationBeginL( aVersion, aExpirationDelta );
+
+ DLTRACEOUT((""));
+ }
+
+void CNcdLoadRootNodeOperation::ConfigurationQueryL(
+ MNcdConfigurationProtocolQuery* aQuery )
+ {
+ DLTRACEIN((""));
+ DASSERT( !iConfQuery );
+ CleanupDeletePushL( aQuery );
+ // create a query object form the protocol entity
+ iConfQuery = CNcdQuery::NewL( *aQuery, IsHttpsUri( *iServerUri ) );
+ CleanupStack::Pop( aQuery );
+
+ // Pass ownership to default observer.
+ DASSERT( iDefaultConfigurationProtocolObserver != NULL );
+ iDefaultConfigurationProtocolObserver->ConfigurationQueryL( aQuery );
+ DLTRACEOUT((""));
+ }
+
+void CNcdLoadRootNodeOperation::ClientConfigurationL(
+ MNcdConfigurationProtocolClientConfiguration* aConfiguration )
+ {
+ DLTRACEIN((""));
+
+ CleanupDeletePushL( aConfiguration );
+ if ( !iNodeDbLocked )
+ {
+ iNodeManager->LockNodeDbL( TUid::Uid( iClientUid ) );
+ iNodeDbLocked = ETrue;
+ }
+ DLINFO(("detail count:%d", aConfiguration->DetailCount()));
+
+ // Parse access point data from client configuration response.
+ iAccessPointManager.ParseAccessPointDataFromClientConfL(
+ *aConfiguration, iPendingMessage->Session().Context().FamilyId() );
+
+ iBundleInsertIndex = 0;
+
+ for( TInt i = 0 ; i < aConfiguration->DetailCount() ; i++ )
+ {
+ const MNcdConfigurationProtocolDetail& detail = aConfiguration->DetailL( i );
+ DLINFO((_L("detail: id=%S value=%S"), &detail.Id(), &detail.Value() ));
+
+ if ( detail.Id() != KContentSources )
+ {
+ continue;
+ }
+ const RPointerArray<MNcdConfigurationProtocolDetail>& csDetails =
+ detail.Details();
+ DLINFO(("csDetails count=%d", csDetails.Count()));
+ for ( TInt j = 0 ; j < csDetails.Count() ; j++ )
+ {
+ MNcdConfigurationProtocolDetail* csDetail = csDetails[j];
+ DLINFO((_L("csDetail: id=%S value=%S"), &csDetail->Id(), &csDetail->Value() ));
+ if ( csDetail->Id() != KNameSpace )
+ {
+ continue;
+ }
+
+ if ( csDetail->GroupId() == KCatalogBundle )
+ {
+ ParseCatalogBundleL( *csDetail );
+ continue;
+ }
+
+ // create a content source
+ // The parameter is the parent node identifier.
+ CNcdContentSource* contentSource =
+ CNcdContentSource::NewLC( *iRootNodeIdentifier );
+ contentSource->SetNameSpaceL( csDetail->Value() );
+
+ // get details
+ const RPointerArray<MNcdConfigurationProtocolDetail>& nsDetails =
+ csDetail->Details();
+ DLINFO(("nsDetails count=%d", nsDetails.Count()));
+ for ( TInt k = 0 ; k < nsDetails.Count() ; k++ )
+ {
+ MNcdConfigurationProtocolDetail* nsDetail = nsDetails[k];
+ DLINFO((_L("nsDetail: id=%S value=%S"), &nsDetail->Id(), &nsDetail->Value() ));
+ if ( nsDetail->Id() == KUri )
+ {
+ contentSource->SetUriL( nsDetail->Value() );
+ }
+ }
+
+ // get contents
+ const RPointerArray<MNcdConfigurationProtocolContent>& nsContents =
+ csDetail->Contents();
+ DLINFO(("nsContents count=%d", nsContents.Count()));
+ for ( TInt l = 0 ; l < nsContents.Count() ; l++ )
+ {
+ MNcdConfigurationProtocolContent* nsContent = nsContents[l];
+ DLINFO((_L("nsContent: key=%S value=%S"), &nsContent->Key(), &nsContent->Value() ));
+ if ( nsContent->Key() == KProvider )
+ {
+ contentSource->SetProviderL( nsContent->Value() );
+ }
+ else if ( nsContent->Key() == KId )
+ {
+ // Notice that the the content source ids should be node identifiers.
+ // Not the actual metadata identifiers. So, append the root info
+ // in front of the value gotten from the server.
+ CNcdNodeIdentifier* contentIdentifier =
+ CNcdNodeIdentifier::NewLC( contentSource->NameSpace(),
+ nsContent->Value(),
+ iRootNodeIdentifier->ClientUid() );
+ CNcdNodeIdentifier* actualNodeIdentifier =
+ NcdNodeIdentifierEditor::CreateNodeIdentifierLC( *iRootNodeIdentifier,
+ *contentIdentifier );
+ DLINFO((_L("Actual nodeidentifier for content source: %S"),
+ &actualNodeIdentifier->NodeId()));
+ contentSource->SetNodeIdL( actualNodeIdentifier->NodeId() );
+ CleanupStack::PopAndDestroy( actualNodeIdentifier );
+ CleanupStack::PopAndDestroy( contentIdentifier );
+ }
+ else if ( nsContent->Key() == KAlwaysVisible )
+ {
+ TBool visible = EFalse;
+ NcdProtocolUtils::DesToBool( visible, nsContent->Value() );
+ contentSource->SetAlwaysVisible( visible );
+ }
+ else if ( nsContent->Key() == KTransparent )
+ {
+ TBool transparent = EFalse;
+ NcdProtocolUtils::DesToBool( transparent, nsContent->Value() );
+ contentSource->SetTransparent( transparent );
+ }
+ }
+
+ DLINFO((_L("content source: namespace=%S, uri=%S, provider=%S, nodeid=%S"),
+ &contentSource->NameSpace(),
+ &contentSource->Uri(),
+ &contentSource->Provider(),
+ &contentSource->NodeId()));
+ iContentSourceMap->AppendContentSourceL( contentSource );
+ CleanupStack::Pop( contentSource );
+ iBundleInsertIndex++;
+ }
+ }
+
+ CleanupStack::Pop( aConfiguration );
+ // Pass ownership to default observer.
+ DASSERT( iDefaultConfigurationProtocolObserver != NULL );
+ iDefaultConfigurationProtocolObserver->ClientConfigurationL( aConfiguration );
+ DLTRACEOUT((""));
+ }
+
+void CNcdLoadRootNodeOperation::ConfigurationDetailsL(
+ CArrayPtr<MNcdConfigurationProtocolDetail>* aDetails )
+ {
+ DLTRACEIN((""));
+
+ // Pass ownership to default observer.
+ DASSERT( iDefaultConfigurationProtocolObserver != NULL );
+ iDefaultConfigurationProtocolObserver->ConfigurationDetailsL( aDetails );
+
+ DLTRACEOUT((""));
+ }
+
+void CNcdLoadRootNodeOperation::ConfigurationActionRequestL(
+ MNcdConfigurationProtocolActionRequest* aActionRequest )
+ {
+ DLTRACEIN((""));
+ // Pass ownership to default observer.
+ DASSERT( iDefaultConfigurationProtocolObserver != NULL );
+ iDefaultConfigurationProtocolObserver->ConfigurationActionRequestL( aActionRequest );
+ DLTRACEOUT((""));
+ }
+
+void CNcdLoadRootNodeOperation::ConfigurationServerDetailsL( MNcdConfigurationProtocolServerDetails* aServerDetails )
+ {
+ DLTRACEIN((""));
+ // Pass ownership to default observer.
+ DASSERT( iDefaultConfigurationProtocolObserver != NULL );
+ iDefaultConfigurationProtocolObserver->ConfigurationServerDetailsL( aServerDetails );
+ DLTRACEOUT((""));
+ }
+
+void CNcdLoadRootNodeOperation::ConfigurationErrorL( MNcdConfigurationProtocolError* aError )
+ {
+ DLTRACEIN((""));
+ iRootNodeState = EFailed;
+ iError = aError->Code();
+
+ // Pass ownership to default observer.
+ DASSERT( iDefaultConfigurationProtocolObserver != NULL );
+ // Operation already failed, ignore possible error here
+ TRAP_IGNORE(iDefaultConfigurationProtocolObserver->ConfigurationErrorL( aError ));
+
+ RunOperation();
+
+ DLTRACEOUT((""));
+ }
+
+void CNcdLoadRootNodeOperation::ConfigurationEndL()
+ {
+ DLTRACEIN((""));
+ // Pass to default observer.
+ DASSERT( iDefaultConfigurationProtocolObserver != NULL );
+ iDefaultConfigurationProtocolObserver->ConfigurationEndL();
+ DLTRACEOUT((""));
+ }
+
+
+void CNcdLoadRootNodeOperation::Progress( CNcdBaseOperation& aOperation )
+ {
+ (void) aOperation; // suppresses compiler warning
+ DASSERT( iRootNodeState == EReceiveBrowse )
+ DASSERT( aOperation.Type() == ELoadNodeOperation )
+ //CNcdLoadNodeOperationImpl& loadOp =
+ // static_cast<CNcdLoadNodeOperationImpl&>( aOperation );
+
+ /*for ( TInt i = 0 ; i < loadOp.LoadedNodes().Count() ; i++ )
+ {
+ iLoadedNodes.AppendL( loadOp.LoadedNodes()[i] );
+ }*/
+ }
+
+void CNcdLoadRootNodeOperation::QueryReceived( CNcdBaseOperation& /*aOperation*/,
+ CNcdQuery* aQuery )
+ {
+ DASSERT( iRootNodeState == EReceiveBrowse )
+ TRAPD( err, iSubOpQuerys.AppendL( aQuery ) );
+ aQuery->InternalAddRef();
+ if( err != KErrNone )
+ {
+ iError = err;
+ iRootNodeState = EFailed;
+ }
+ RunOperation();
+ }
+
+void CNcdLoadRootNodeOperation::OperationComplete( CNcdBaseOperation* aOperation,
+ TInt aError )
+ {
+ DLTRACEIN(("error=%d", aError));
+ DLINFO((("iRootNodeState = %d"), iRootNodeState ));
+ (void) aError; // suppresses compiler warning
+
+ DASSERT( iRootNodeState == EReceiveBrowse ||
+ iRootNodeState == EBrowseRequest )
+ DASSERT( aOperation->Type() == ELoadNodeOperation )
+
+ DLINFO(("subop count: failed:%d completed:%d total:%d",
+ iFailedSubOps.Count(), iCompletedSubOps.Count(), iSubOps.Count() ));
+
+ TRAPD(err,
+ CNcdLoadNodeOperationImpl* loadOp =
+ static_cast<CNcdLoadNodeOperationImpl*>( aOperation );
+ DASSERT( loadOp->State() == CNcdLoadNodeOperationImpl::EFailed ||
+ loadOp->State() == CNcdLoadNodeOperationImpl::EComplete )
+ if ( loadOp->State() == CNcdLoadNodeOperationImpl::EFailed )
+ {
+ iFailedSubOps.AppendL( loadOp );
+ }
+ else if ( loadOp->State() == CNcdLoadNodeOperationImpl::EComplete )
+ {
+ iCompletedSubOps.AppendL( loadOp );
+ const RPointerArray<CNcdNodeIdentifier>& loadedNodes = loadOp->LoadedNodes();
+ CNcdRootNode& rootNode =
+ iNodeManager->RootNodeL( iRootNodeIdentifier->ClientUid() );
+ CNcdNodeLink& rootLink = rootNode.NodeLinkL();
+ TTime currentTime;
+ currentTime.HomeTime();
+
+ // add loaded nodes from child op to our own array
+ for ( TInt i = 0 ; i < loadedNodes.Count() ; i++ )
+ {
+ CNcdNodeIdentifier* id = CNcdNodeIdentifier::NewLC( *loadedNodes[i] );
+ iLoadedNodes.AppendL( id );
+ CleanupStack::Pop( id );
+ }
+ }
+
+ if ( iRootNodeState == EReceiveBrowse )
+ {
+ // call RunOperation only in this state,
+ // otherwise RunOperation could call itself immediately
+ // after starting a sub op
+ // (sub-op start -> error -> complete callback -> run op )
+ RunOperation();
+ }); //TRAPD
+ if ( err != KErrNone )
+ {
+ iError = err;
+ iRootNodeState = EFailed;
+ RunOperation();
+ }
+ }
+
+void CNcdLoadRootNodeOperation::ConfigurationChangedL()
+ {
+ DLTRACEIN((( "iRootNodeState: %d"), iRootNodeState ));
+ DASSERT( iRootNodeState == EReceiveConf )
+ // Master server address changed. Restart operation.
+ iRootNodeState = EConfRequest;
+ iMasterServerRedirectionState = ERedirecting;
+ }
+
+void CNcdLoadRootNodeOperation::ReceiveMessage(
+ MCatalogsBaseMessage* aMessage,
+ TInt aFunctionNumber )
+ {
+ DLTRACEIN((_L("Handle: %i, aFunctionNumber=%d"), aMessage->Handle(),
+ aFunctionNumber));
+
+ switch ( aFunctionNumber )
+ {
+ case ENCDOperationFunctionGetData:
+ {
+ HandleConfigurationDataRequestMessage( *aMessage );
+ break;
+ }
+ default:
+ {
+ CNcdBaseOperation::ReceiveMessage( aMessage, aFunctionNumber );
+ break;
+ }
+ }
+ }
+
+void CNcdLoadRootNodeOperation::ErrorL( MNcdPreminetProtocolError* aData )
+ {
+ DLTRACEIN((""));
+ // Default observer deletes aData
+ iParser->DefaultObserver().ErrorL( aData );
+ }
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+CNcdLoadRootNodeOperation::CNcdLoadRootNodeOperation(
+ TInt aClientUid,
+ CNcdGeneralManager& aGeneralManager,
+ MCatalogsHttpSession& aHttpSession,
+ MNcdOperationRemoveHandler* aRemoveHandler,
+ MCatalogsSession& aSession )
+ : CNcdBaseOperation( aGeneralManager, aRemoveHandler, ELoadRootNodeOperation,
+ aSession ),
+ iAccessPointManager( aGeneralManager.AccessPointManager() ),
+ iHttpSession( aHttpSession ),
+ iProtocol( aGeneralManager.ProtocolManager() ),
+ iConfigManager( aGeneralManager.ConfigurationManager() ),
+ iClientUid( aClientUid ),
+ iNodeDbLocked( EFalse )
+ {
+ iRootNodeState = EConfRequest;
+ iMasterServerRedirectionState = EBegin;
+ iProgress.iState = 0;
+ iProgress.iOperationId = 0;
+ iProgress.iProgress = 0;
+ iProgress.iMaxProgress = 100;
+ }
+
+
+// ---------------------------------------------------------------------------
+// ?description_if_needed
+// ---------------------------------------------------------------------------
+//
+void CNcdLoadRootNodeOperation::ConstructL()
+ {
+ DLTRACEIN((""));
+ CNcdBaseOperation::ConstructL();
+
+ iConfigResponseBuf = CBufFlat::NewL( 100 );
+ }
+
+// ---------------------------------------------------------------------------
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+HBufC8* CNcdLoadRootNodeOperation::CreateConfRequestLC( CNcdQuery* aQuery )
+ {
+ DLTRACEIN((""));
+ CNcdRequestConfiguration* req =
+ NcdRequestGenerator::CreateConfigurationRequestLC();
+
+ if( aQuery )
+ {
+ DASSERT(( aQuery->Response() == MNcdQuery::EAccepted ));
+
+ MNcdConfigurationProtocolQueryResponse* queryResponse =
+ CreateResponseL( *aQuery );
+ CleanupStack::PushL( queryResponse );
+ req->AddQueryResponseL( queryResponse );
+ CleanupStack::Pop( queryResponse );
+ }
+
+ HBufC8* data = iProtocol.ProcessConfigurationRequestL(
+ iPendingMessage->Session().Context(), *req );
+ CleanupStack::PopAndDestroy( req );
+ CleanupStack::PushL( data );
+ return data;
+ }
+
+
+void CNcdLoadRootNodeOperation::RevertNodesOfBrokenSourcesToCacheL()
+ {
+ DLTRACEIN((""));
+ // Revert the nodes from broken content sources
+ CNcdRootNode& rootNode =
+ iNodeManager->RootNodeL( iRootNodeIdentifier->ClientUid() );
+ CNcdContentSourceMap& oldContentSourceMap = rootNode.ContentSourceMap();
+ DLINFO(("old content source count=%d", oldContentSourceMap.ContentSourceCount() ));
+ for ( TInt i = 0; i < oldContentSourceMap.ContentSourceCount(); i++ )
+ {
+ CNcdContentSource& oldSource = oldContentSourceMap.ContentSource( i );
+
+ // Note that the content sources contain node identifiers,
+ // not metadata identifiers.
+ RPointerArray<CNcdNodeIdentifier>& oldNodes =
+ oldContentSourceMap.NodesL( oldSource );
+
+ if ( iContentSourceMap->HasContentSource( oldSource ) )
+ {
+ DLINFO(("same content source"));
+ CNcdContentSource& source =
+ iContentSourceMap->ContentSourceL( oldSource );
+ if ( source.IsBroken() )
+ {
+ // Broken content source, revert the nodes belonging to this source
+ DLINFO(("Source was broken, revert %d nodes", oldNodes.Count()));
+ for ( TInt i = 0; i < oldNodes.Count(); i++ )
+ {
+ RevertNodeL( *oldNodes[i], source );
+ // Add the node to the new content source map also since the root node's old
+ // content source map is replaced with the new one.
+ CNcdNodeIdentifier* identifier = CNcdNodeIdentifier::NewLC( *oldNodes[i] );
+ iContentSourceMap->AddNodeToContentSourceL( identifier, source );
+ CleanupStack::Pop( identifier );
+ }
+
+
+ }
+ }
+ }
+ }
+
+
+void CNcdLoadRootNodeOperation::RevertNodeL(
+ const CNcdNodeIdentifier& aNodeIdentifier,
+ const CNcdContentSource& aContentSource )
+ {
+ DLTRACEIN((_L("node ns: %S, id: %S"),
+ &aNodeIdentifier.NodeNameSpace(),
+ &aNodeIdentifier.NodeId() ));
+
+ iNodeManager->RevertNodeFromTempCacheL( aNodeIdentifier );
+ CNcdNode* node = iNodeManager->NodePtrL( aNodeIdentifier );
+ DASSERT( node );
+
+ // The node is root's child, it must be added as a child since it was removed from the
+ // child list as it was moved to temp cache.
+ CNcdNodeIdentifier* parentId = NcdNodeIdentifierEditor::ParentOfLC( aNodeIdentifier );
+ if ( parentId->Equals( *iRootNodeIdentifier ) )
+ {
+ DLINFO(("Child of root"));
+ CNcdRootNode& rootNode =
+ iNodeManager->RootNodeL( iRootNodeIdentifier->ClientUid() );
+ CNcdNodeIdentifier* metaOfChild =
+ NcdNodeIdentifierEditor::CreateMetaDataIdentifierLC( aNodeIdentifier );
+ iNodeManager->AddToParentL(
+ *parentId, *metaOfChild, CNcdNodeFactory::ENcdNodeRoot, CNcdNodeFactory::ENcdNormalNode,
+ CNcdNodeFactory::NodePurposeL( *node ), CNcdNodeManager::EInsert,
+ iContentSourceMap->GetInsertIndexL( aContentSource, *parentId ) );
+ CleanupStack::PopAndDestroy( metaOfChild );
+ }
+ CleanupStack::PopAndDestroy( parentId );
+ }
+
+
+void CNcdLoadRootNodeOperation::AddNodesToDifferentParentsL()
+ {
+ DLTRACEIN((""));
+
+ // Move nodes from iBundleFolders to iLoadedNodes to update the bundle folders in proxy
+ // side.
+ User::LeaveIfError(
+ iLoadedNodes.Reserve( iLoadedNodes.Count() + iContentSourceMap->BundleFolderCount() ) );
+
+ for ( TInt i = 0; i < iContentSourceMap->BundleFolderCount(); i++ )
+ {
+ // Append node ids to the loaded nodes list. These identifiers are
+ // returned to the proxy side when the operation is completed.
+ // Note that the content sources contain node identifiers,
+ // not metadata identifiers.
+ CNcdNodeIdentifier* bundle = CNcdNodeIdentifier::NewLC(
+ iContentSourceMap->BundleFolder( i ) );
+
+ DLINFO((_L("Root Bundle ns: %S, id_: %S"),
+ &bundle->NodeNameSpace(),
+ &bundle->NodeId()));
+
+ iLoadedNodes.AppendL( bundle );
+
+ // Do not delete because array takes ownership.
+ CleanupStack::Pop( bundle );
+ }
+
+ DLTRACEOUT(("Ok"));
+ }
+
+void CNcdLoadRootNodeOperation::SetAlwaysVisibleFlagsL()
+ {
+ DLTRACEIN((""));
+ for ( TInt i = 0; i < iContentSourceMap->ContentSourceCount(); i++ )
+ {
+ CNcdContentSource& contentSource = iContentSourceMap->ContentSource( i );
+ if ( !contentSource.AlwaysVisible() )
+ {
+ continue;
+ }
+ // Get the reference. So, no need to close this array.
+ RPointerArray<CNcdNodeIdentifier>& nodes = iContentSourceMap->NodesL( contentSource );
+ TRAPD( err,
+ {
+ for ( TInt i = 0; i < nodes.Count(); i++ )
+ {
+ // Because content sources use node id
+ CNcdNodeIdentifier* nodeId = nodes[i];
+
+ // Check whether the node is loaded completely
+ for ( TInt i = 0; i < iLoadedNodes.Count(); i++ )
+ {
+ if ( iLoadedNodes[i]->Equals( *nodeId ) )
+ {
+ CNcdNode& node = iNodeManager->NodeL( *nodeId );
+ CNcdNodeMetaData& metadata = node.NodeMetaDataL();
+ metadata.SetAlwaysVisible( ETrue );
+
+ // DLMAIN-523, "Always visible information is not
+ // persisted to disk"
+ iNodeManager->DbSaveNodeMetaDataL( metadata );
+ break;
+ }
+ }
+ }
+ }); // TRAP
+
+
+ if ( err == KErrNotFound )
+ {
+ DASSERT( EFalse );
+ }
+ else if ( err != KErrNone )
+ {
+ User::Leave( err );
+ }
+
+ }
+ DLTRACEOUT(("Ok."));
+ }
+
+
+void CNcdLoadRootNodeOperation::ParseCatalogBundleL(
+ const MNcdConfigurationProtocolDetail& aDetail )
+ {
+ DLTRACEIN((""));
+ DASSERT( aDetail.GroupId() == KCatalogBundle );
+ DASSERT( aDetail.Id() == KNameSpace );
+
+ const RPointerArray<MNcdConfigurationProtocolContent>& bundleContents =
+ aDetail.Contents();
+
+ const TDesC* bundleId = NULL;
+ for ( TInt i = 0; i < bundleContents.Count(); i++ )
+ {
+ const MNcdConfigurationProtocolContent* content = bundleContents[i];
+ if ( content->Key() == KId )
+ {
+ bundleId = &content->Value();
+ break;
+ }
+ }
+
+ // Create folder for catalog bundle.
+ DASSERT( bundleId );
+
+ CNcdNodeIdentifier* metaDataId = CNcdNodeIdentifier::NewLC(
+ aDetail.Value(), *bundleId, iPendingMessage->Session().Context().FamilyId() );
+ DLINFO((_L("Bundle metaid ns: %S, id: %S"),
+ &metaDataId->NodeNameSpace(),
+ &metaDataId->NodeId()));
+
+ // The id has been gotten from the net server. So, it is same as
+ // the metadata id that should be used here. Note that the creation of bundle requires the
+ // metadataid (instead actual nodeid) for the parameter, and that we have here :)
+ // Because the bundle folder is always the child of the root, the function can automatically
+ // create the correct node id for the folder.
+ CNcdNodeFolder& bundleFolder =
+ iNodeManager->CreateBundleFolderL( *metaDataId );
+
+ // Create the link for the bundle
+ CNcdNodeLink& link = bundleFolder.CreateAndSetLinkL();
+
+ // Also, notice that it is essential to insert the metadata identifier into the
+ // link info. So, the right metadata will be found when the bundle is opened
+ // from the database. For example when application has been started.
+ link.SetMetaDataIdentifierL( *metaDataId );
+
+ // Create meta data for bundle folder.
+ CNcdNodeMetaData& bundleMetaData =
+ iNodeManager->CreateNodeMetaDataL( *metaDataId, CNcdNodeFactory::ENcdNodeFolder );
+
+ for ( TInt i = 0; i < bundleContents.Count(); i++ )
+ {
+ const MNcdConfigurationProtocolContent* content = bundleContents[i];
+ if ( content->Key() == KName )
+ {
+ bundleMetaData.SetNodeNameL( content->Value() );
+ }
+ else if ( content->Key() == KDescription )
+ {
+ bundleMetaData.SetDescriptionL( content->Value() );
+ }
+ else if ( content->Key() == KValidUntil )
+ {
+ link.SetValidUntilDelta(
+ NcdProtocolUtils::DesDecToIntL( content->Value() ) );
+ }
+ else if ( content->Key() == KViewType )
+ {
+ static_cast<CNcdBundleFolder&>( bundleFolder ).SetViewTypeL(
+ content->Value() );
+ }
+ }
+
+ const RPointerArray<MNcdConfigurationProtocolDetail>& subCatalogs =
+ aDetail.Details();
+
+ // Parse icon data.
+ for ( TInt i = 0; i < subCatalogs.Count(); i++ )
+ {
+ MNcdConfigurationProtocolDetail* detail = subCatalogs[i];
+ if ( detail->Id() != KIcon )
+ {
+ continue;
+ }
+ const RPointerArray<MNcdConfigurationProtocolContent> iconContents =
+ detail->Contents();
+ CNcdNodeIcon* icon = CNcdNodeIcon::NewL( *iNodeManager, bundleMetaData );
+ bundleMetaData.SetIcon( icon );
+
+ for ( TInt i = 0; i < iconContents.Count(); i++ )
+ {
+ MNcdConfigurationProtocolContent* content = iconContents[i];
+ if ( content->Key() == KId )
+ {
+ icon->SetIconIdL( content->Value() );
+ }
+ else if ( content->Key() == KData )
+ {
+ const TDesC& iconData = content->Content();
+ HBufC8* iconData8 = HBufC8::NewLC( iconData.Length() );
+ iconData8->Des().Copy( iconData );
+ HBufC8* decodedData =
+ NcdProtocolUtils::DecodeBase64LC( *iconData8 );
+
+ // Save the icon data to database.
+ CNcdNodeIdentifier* iconId = CNcdNodeIdentifier::NewLC(
+ metaDataId->NodeNameSpace(), icon->IconId(),
+ icon->Uri(), metaDataId->ClientUid() );
+ iNodeManager->DbSaveIconDataL( *iconId, *decodedData );
+ CleanupStack::PopAndDestroy( iconId );
+ CleanupStack::PopAndDestroy( decodedData );
+ CleanupStack::PopAndDestroy( iconData8 );
+ }
+ else if ( content->Key() == KUri && content->Value() != KNullDesC )
+ {
+ DLTRACE((_L("Setting bundle icon uri: %S"), &content->Value() ));
+ icon->SetUriL( content->Value() );
+ }
+ }
+ }
+
+ iNodeManager->DbSaveNodeMetaDataL( bundleMetaData );
+
+ // Set the metadata to the bundle folder because it was not set during creation.
+ bundleFolder.SetNodeMetaDataL( bundleMetaData );
+
+ // Set the bundle folder as child of root node.
+ // Bundle folders are always children of the root.
+ iNodeManager->AddToParentL( *iRootNodeIdentifier, *metaDataId,
+ CNcdNodeFactory::ENcdNodeRoot,
+ CNcdNodeFactory::ENcdNormalNode,
+ CNcdNodeFactory::ENcdBundleNode,
+ CNcdNodeManager::EReplace, iBundleInsertIndex );
+ CleanupStack::PopAndDestroy( metaDataId );
+ metaDataId = NULL;
+
+ // Because AddToParentL only saves the parent information after child is added to it
+ // we should always save the bundle node here. So, it will be usable after client is
+ // restarted.
+ iNodeManager->DbSaveNodeL( bundleFolder );
+
+ // Disabled bundle handling temporarily because of NCDALTCI-667
+ // Bundles are now loaded explicitly with CNcdLoadBundleNodeOperation because
+ // otherwise transparent folders are not refreshed when they are supposed to
+/*
+ // Parse sub catalogs.
+ for ( TInt i = 0; i < subCatalogs.Count(); i++ )
+ {
+ MNcdConfigurationProtocolDetail* subCatalog = subCatalogs[i];
+ if ( subCatalog->GroupId() != KSubCatalogs )
+ {
+ continue;
+ }
+
+ // Get namespace
+ DASSERT( subCatalog->Id() == KNameSpace );
+ const TDesC& nameSpace = subCatalog->Value();
+ DLINFO((_L("Bundle subcatalog ns(/value): %S"),
+ &subCatalog->Value()));
+
+ //Get uri
+ const TDesC* uri = NULL;
+ const RPointerArray<MNcdConfigurationProtocolDetail>& subCatalogDetails =
+ subCatalog->Details();
+ for ( TInt i = 0; i < subCatalogDetails.Count(); i++ )
+ {
+ const MNcdConfigurationProtocolDetail* detail = subCatalogDetails[i];
+ if ( detail->Id() == KUri )
+ {
+ uri = &detail->Value();
+ DLINFO((_L("Bundle subcatalog detail uri(/value): %S"),
+ &detail->Value()));
+ }
+ }
+ if( uri == NULL )
+ {
+ DLTRACE(("Uri not found -> incomplete, skip"));
+ continue;
+ }
+
+ CNcdNodeIdentifier* subCatalogIdentifier = NULL;
+ const TDesC* provider = NULL;
+ TBool transparent = EFalse;
+ const RPointerArray<MNcdConfigurationProtocolContent>& subCatalogContents =
+ subCatalog->Contents();
+ for ( TInt i = 0; i < subCatalogContents.Count(); i++ )
+ {
+ const MNcdConfigurationProtocolContent* content = subCatalogContents[i];
+ if ( content->Key() == KId )
+ {
+ // Notice that the the content source ids should be node identifiers.
+ // Not the actual metadata identifiers. So, append the root info
+ // in front of the value gotten from the server.
+ CNcdNodeIdentifier* contentIdentifier =
+ CNcdNodeIdentifier::NewLC( nameSpace,
+ content->Value(),
+ *uri,
+ bundleFolder.Identifier().ClientUid() );
+
+ subCatalogIdentifier =
+ NcdNodeIdentifierEditor::CreateNodeIdentifierLC( bundleFolder.Identifier(),
+ *contentIdentifier );
+ CleanupStack::Pop( subCatalogIdentifier );
+ CleanupStack::PopAndDestroy( contentIdentifier );
+ CleanupStack::PushL( subCatalogIdentifier );
+ DLINFO((_L("Bundle subcatalog content set node id(/value): %S"),
+ &subCatalogIdentifier->NodeId()));
+ }
+ else if ( content->Key() == KProvider )
+ {
+ provider = &content->Value();
+ DLINFO((_L("Bundle subcatalog content set provider (/value): %S"),
+ provider));
+ }
+ else if ( content->Key() == KTransparent )
+ {
+ NcdProtocolUtils::DesToBool( transparent, content->Value() );
+ }
+ }
+
+ if( subCatalogIdentifier == NULL )
+ {
+ DLTRACE(("Id not found -> incomplete, skip"));
+ continue;
+ }
+
+ // Create the actual child folder
+ CNcdNodeFolder* bundleChild = NULL;
+ if( transparent )
+ {
+ bundleChild = &iNodeManager->CreateNodeFolderL(
+ CNcdNodeFactory::ENcdTransparentNode, *subCatalogIdentifier );
+ }
+ else
+ {
+ bundleChild = &iNodeManager->CreateNodeFolderL(
+ CNcdNodeFactory::ENcdNormalNode, *subCatalogIdentifier );
+ }
+ CleanupStack::PopAndDestroy( subCatalogIdentifier );
+
+ // Create a link for the child
+ CNcdNodeLink& bundleChildLink = bundleChild->CreateAndSetLinkL();
+
+ if ( provider )
+ {
+ bundleChildLink.SetCatalogsSourceNameL( *provider );
+ }
+
+ // Also, notice that it is essential to insert the metadata identifier into the
+ // link info. So, the right metadata will be found when the node is opened
+ // from the database. For example when application has been started.
+ CNcdNodeIdentifier* bundleChildMeta =
+ NcdNodeIdentifierEditor::CreateMetaDataIdentifierLC( bundleChild->Identifier() );
+ bundleChildLink.SetMetaDataIdentifierL( *bundleChildMeta );
+ CleanupStack::PopAndDestroy( bundleChildMeta );
+
+ // Set uri for the child
+ bundleChildLink.SetServerUriL( *uri );
+
+ // Add the child to the bundle.
+ if ( transparent )
+ {
+ iNodeManager->AddToParentL( bundleFolder.Identifier(),
+ bundleChildLink.MetaDataIdentifier(),
+ CNcdNodeFactory::ENcdNodeFolder,
+ CNcdNodeFactory::ENcdBundleNode,
+ CNcdNodeFactory::ENcdTransparentNode,
+ CNcdNodeManager::EAppend,
+ 0,
+ transparent );
+ }
+ else
+ {
+ iNodeManager->AddToParentL( bundleFolder.Identifier(),
+ bundleChildLink.MetaDataIdentifier(),
+ CNcdNodeFactory::ENcdNodeFolder,
+ CNcdNodeFactory::ENcdBundleNode,
+ CNcdNodeFactory::ENcdNormalNode,
+ CNcdNodeManager::EAppend,
+ 0,
+ transparent );
+ }
+ iNodeManager->DbSaveNodeL( *bundleChild );
+ }
+ */
+ iContentSourceMap->AppendFolderL( bundleFolder.Identifier(), iBundleInsertIndex );
+
+ // increment insert index for next bundle
+ iBundleInsertIndex++;
+
+ // Because AddToParentL only saves the parent information after child is added to it
+ // we should always save the bundle node here. So, it will be usable after client is
+ // restarted.
+
+ // Unnecessary while bundle handling is disabled
+ //iNodeManager->DbSaveNodeL( bundleFolder );
+ }
+
+
+TBool CNcdLoadRootNodeOperation::ContainsNode(
+ const RPointerArray<CNcdNodeIdentifier>& aNodes,
+ const CNcdNodeIdentifier& aNode)
+ {
+ for ( TInt i = 0; i < aNodes.Count(); i++ )
+ {
+ CNcdNodeIdentifier* nodeId = aNodes[i];
+ DASSERT( nodeId->ClientUid() == aNode.ClientUid() );
+ if ( nodeId->Equals( aNode ) )
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+
+void CNcdLoadRootNodeOperation::HandleConfigurationDataRequestMessage(
+ MCatalogsBaseMessage& aMessage )
+ {
+ DLTRACEIN((""));
+ TPtr8 data = iConfigResponseBuf->Ptr( 0 );
+
+ TRAPD( err, aMessage.CompleteAndReleaseL( data, KErrNone ) );
+ if ( err != KErrNone )
+ {
+ aMessage.CompleteAndRelease( err );
+ }
+ }
+// ---------------------------------------------------------------------------
+// From class CNcdBaseOperation.
+// ?implementation_description
+// ---------------------------------------------------------------------------
+//
+TInt CNcdLoadRootNodeOperation::RunOperation()
+ {
+ DLTRACEIN((("this-ptr: %x"), this ));
+
+ TInt err( KErrNone );
+ TRAP( err, DoRunOperationL() );
+
+ if ( err != KErrNone )
+ {
+ DLTRACE(("error: %d", err));
+ Cancel();
+ iRootNodeState = EFailed;
+ iError = err;
+ if ( iPendingMessage )
+ {
+ // ignoring error because operation already failed
+ CNcdBaseOperation::CompleteMessage( iPendingMessage,
+ ENCDOperationMessageCompletionError, iError );
+ }
+ }
+
+ DLTRACEOUT(("err: %d", err));
+ return err;
+ }
+
+
+void CNcdLoadRootNodeOperation::DoRunOperationL()
+ {
+ DLTRACEIN((""));
+ switch ( iRootNodeState )
+ {
+ case EConfRequest:
+ {
+ DLTRACE((_L("->EConfRequest")));
+ DASSERT ( iPendingMessage );
+
+ CNcdRootNode& root =
+ iNodeManager->CreateRootL( iPendingMessage->Session().Context() );
+ root.CreateAndSetLinkL();
+
+ if ( !iRootNodeIdentifier )
+ {
+ // create identifier for root node
+ iRootNodeIdentifier = CNcdNodeIdentifier::NewL( root.Identifier() );
+
+ // Store previous list only if some children have been previously loaded.
+ if( root.ChildrenPreviouslyLoaded() )
+ {
+ root.StoreChildrenToPreviousListL();
+ }
+
+ // Create previous lists of children for new checking.
+ iChildEntityMaps.ResetAndDestroy();
+ iNodeManager->SeenInfo().CreatePreviousListsForChildrenL( root, iChildEntityMaps );
+
+ iNodeManager->BackupAndClearCacheL( *iRootNodeIdentifier );
+ iNodeManager->LockNodeDbL( TUid::Uid( iClientUid ) );
+ iNodeDbLocked = ETrue;
+ }
+
+ // remove old content sources
+ delete iContentSourceMap;
+ iContentSourceMap = NULL;
+ iContentSourceMap = CNcdContentSourceMap::NewL();
+
+ delete iServerUri;
+ iServerUri = NULL;
+ iServerUri = iConfigManager.MasterServerAddressL(
+ iPendingMessage->Session().Context() ).AllocL();
+
+ HBufC8* request = CreateConfRequestLC( iConfQuery );
+
+ if ( iConfQuery )
+ {
+ iConfQuery->InternalRelease();
+ iConfQuery = NULL;
+ }
+
+ DLINFO(( "request= %S", request ));
+
+ // create transaction
+ iGeneralManager.HttpUtils().CreateTransactionL(
+ iHttpSession,
+ iTransaction,
+ *iServerUri,
+ *this,
+ *request );
+
+
+ // create parser
+ delete iParser;
+ iParser = NULL;
+ iParser = iProtocol.CreateParserL(
+ iPendingMessage->Session().Context(), *iServerUri );
+ MNcdParserObserverBundle& observers = iParser->Observers();
+ observers.SetParserObserver( this );
+ iDefaultConfigurationProtocolObserver =
+ observers.ConfigurationProtocolObserver();
+ observers.SetConfigurationProtocolObserver( this );
+ observers.SetInformationObserver( this );
+
+ iConfigManager.AddObserverL( *this, iPendingMessage->Session().Context() );
+
+ iParser->BeginAsyncL();
+
+ // start transaction
+ User::LeaveIfError( iTransaction->Start() );
+ CleanupStack::PopAndDestroy( request );
+
+
+ iRootNodeState = EReceiveConf;
+ DLTRACE(( "->EConfRequest done" ));
+ break;
+ }
+
+ case EReceiveConf:
+ {
+ DLTRACE((_L("->EReceiveConf")));
+ // Should send progress only if progress is made
+
+ if ( iPendingMessage && iSendProgress )
+ {
+ User::LeaveIfError( CNcdBaseOperation::CompleteMessage( iPendingMessage,
+ ENCDOperationMessageCompletionProgress,
+ iProgress, KErrNone ) );
+ iSendProgress = EFalse;
+ }
+ DLTRACE((_L("->EReceiveConf done")));
+ break;
+ }
+
+ case EConfQuery:
+ {
+ DLTRACE(("->EConfQuery"));
+ DASSERT( iConfQuery );
+ DASSERT( iConfQuery->Response() == MNcdQuery::EAccepted ||
+ iConfQuery->Response() == MNcdQuery::ERejected )
+ if ( iConfQuery->Response() == MNcdQuery::EAccepted)
+ {
+ DLTRACE(("Query accepted"));
+ if ( iConfQuery->ItemCount() == 0 )
+ {
+ // SPECIAL CASE:
+ // querys with no items don't need responding to
+ // e.g. a server message
+ if( iContentSourceMap->ContentSourceCount() > 0 )
+ {
+ // content sources received in the earlier response,
+ // start loading them
+ iRootNodeState = EBrowseRequest;
+ }
+ else if ( iMasterServerRedirectionState == ERedirecting )
+ {
+ // Redirect. Delete conf query since it does not need
+ // responding to new master server.
+ DLINFO(("Redirect"));
+ iConfQuery->InternalRelease();
+ iConfQuery = NULL;
+ iRootNodeState = EConfRequest;
+ }
+ else
+ {
+ // no content sources received
+ // e.g. server didn't give any content sources
+ // with the set provisioning, only a
+ // "service not available..." message is received
+ iRootNodeState = EComplete;
+ }
+ }
+ else
+ {
+ // NORMAL CASE:
+ // Respond to the query in a new request
+ iRootNodeState = EConfRequest;
+ }
+ }
+ else
+ {
+ DLTRACE(("Query rejected"));
+ if ( iConfQuery->IsOptional() )
+ {
+ DLTRACE(("Query is optional"));
+ if( iContentSourceMap->ContentSourceCount() > 0 )
+ {
+ DLTRACE(("Content sources received previously, start loading"));
+ // content sources received in the earlier response,
+ // start loading them
+ iRootNodeState = EBrowseRequest;
+ }
+ else if ( iMasterServerRedirectionState == ERedirecting )
+ {
+ // Redirect. Delete conf query since it does not need
+ // responding to new master server.
+ DLINFO(("Redirect"));
+ iConfQuery->InternalRelease();
+ iConfQuery = NULL;
+ iRootNodeState = EConfRequest;
+ }
+ else
+ {
+ DLTRACE(("No sources received!"));
+ // no content sources received with an optional query
+ // this should never happen!
+ iError = KNcdErrorNoContentSources;
+ iRootNodeState = EFailed;
+ }
+ }
+ else
+ {
+ DLTRACE(("Query not optional, operation will stop!"));
+ iRootNodeState = EComplete;
+ }
+ }
+
+ RunOperation();
+ DLTRACE(("->EConfQuery done"));
+ break;
+ }
+
+ case EBrowseRequest:
+ {
+ DLTRACE((_L("->EBrowseRequest")));
+
+ iSubOps.ResetAndDestroy();
+
+ // Create load node op for each content source.
+ DLINFO((("Content source count=%d"), iContentSourceMap->ContentSourceCount()));
+ for ( TInt i = 0 ; i < iContentSourceMap->ContentSourceCount() ; i++ )
+ {
+ CNcdContentSource& contentSource =
+ iContentSourceMap->ContentSource( i );
+ DLINFO((_L("content source: namespace=%S, uri=%S, id=%S"),
+ &contentSource.NameSpace(), &contentSource.Uri(), &contentSource.NodeId()));
+
+ // The parent identifier should be root here.
+ // So, no need to change that parent identifier info. It does not
+ // differ from the metadataid because root does not have metadata.
+ CNcdLoadNodeOperationImpl* loadOp =
+ CNcdLoadNodeOperationImpl::NewLC(
+ contentSource,
+ iContentSourceMap,
+ contentSource.ParentIdentifier(),
+ iGeneralManager,
+ iHttpSession,
+ iRemoveHandler,
+ iSession );
+
+ loadOp->AddObserverL( this );
+ iSubOps.AppendL( loadOp );
+ CleanupStack::Pop( loadOp );
+ // error code ignored, errors handled via callback
+ loadOp->Start();
+ }
+
+ iRootNodeState = EReceiveBrowse;
+ DLINFO(("subop count: failed:%d completed:%d total:%d",
+ iFailedSubOps.Count(), iCompletedSubOps.Count(), iSubOps.Count() ));
+ if ( iFailedSubOps.Count() + iCompletedSubOps.Count() ==
+ iSubOps.Count() )
+ {
+ // all sub ops have either completed or failed
+ // -> this operation is now complete
+ iRootNodeState = EComplete;
+ if ( iFailedSubOps.Count() > 0 )
+ {
+ DLINFO(("Some catalogs failed to load"));
+ iError = KNcdErrorSomeCatalogsFailedToLoad;
+ }
+ RunOperation();
+ }
+
+ DLTRACE((_L("->EBrowseRequest done")));
+
+ break;
+ }
+
+ case EReceiveBrowse:
+ {
+ DLTRACE((_L("->EReceiveBrowse")));
+ if( iSubOpQuerys.Count() > 0 )
+ {
+ // send sub op query to proxy
+ CNcdBaseOperation::QueryReceivedL( iSubOpQuerys[0] );
+ // release own reference and remove
+ iSubOpQuerys[0]->InternalRelease();
+ iSubOpQuerys.Remove( 0 );
+ }
+ else if ( iPendingMessage && iLoadedNodes.Count() > 0 )
+ {
+ SetAlwaysVisibleFlagsL();
+
+ // send updated nodes identifiers to proxy
+ User::LeaveIfError( CompleteMessage( iPendingMessage,
+ ENCDOperationMessageCompletionNodesUpdated,
+ iProgress,
+ iLoadedNodes,
+ KErrNone ) );
+
+ iLoadedNodes.ResetAndDestroy();
+ }
+ else if ( iFailedSubOps.Count() + iCompletedSubOps.Count() ==
+ iSubOps.Count() )
+ {
+ // all sub ops have either completed or failed
+ // -> this operation is now complete
+ iRootNodeState = EComplete;
+ if ( iFailedSubOps.Count() > 0 )
+ {
+ DLINFO(("Some catalogs failed to load"));
+ iError = KNcdErrorSomeCatalogsFailedToLoad;
+ }
+ RunOperation();
+ }
+
+ DLTRACE((_L("->EReceiveBrowse done")));
+ break;
+ }
+
+ case EComplete:
+ {
+ DLTRACE((_L("->EComplete")));
+
+ CNcdRootNode& rootNode =
+ iNodeManager->RootNodeL( iRootNodeIdentifier->ClientUid() );
+ // Compare the ContentSourceMaps of previous root node load and this
+ // load and delete the nodes that were removed from server.
+ if ( iContentSourceMap && ( iContentSourceMap->ContentSourceCount() > 0 ||
+ iContentSourceMap->BundleFolderCount() > 0 ) )
+ {
+ DLINFO(("Content source map count"));
+ RevertNodesOfBrokenSourcesToCacheL();
+ AddNodesToDifferentParentsL();
+ SetAlwaysVisibleFlagsL();
+
+ // Give the new content source map to root node to be used in the next
+ // root node load
+ rootNode.SetContentSourceMap( iContentSourceMap );
+ // Root node takes the ownership.
+ // So, set NULL here. So this class will not delete this.
+ iContentSourceMap = NULL;
+ // Now the RAM node cache should be updated correctly, save it to database.
+ iNodeManager->UnlockNodeDb( TUid::Uid( iClientUid ) );
+ iNodeDbLocked = EFalse;
+ iNodeManager->DbSaveNodesL( *iRootNodeIdentifier );
+ }
+
+ if( iNodeDbLocked )
+ {
+ iNodeManager->UnlockNodeDb( TUid::Uid( iClientUid ) );
+ iNodeDbLocked = EFalse;
+ }
+
+ iNodeManager->ClearTempCacheL( *iRootNodeIdentifier );
+
+ // Set the children loaded flag so that next refresh stores
+ // previous child list (needed for new checking)
+ if( rootNode.ChildCount() )
+ {
+ rootNode.SetChildrenPreviouslyLoaded();
+ iNodeManager->DbSaveNodeL( rootNode );
+ }
+ // Check new status
+ iNodeManager->SeenInfo().StorePreviousListsToExistingChildrenL(
+ rootNode,
+ iChildEntityMaps );
+
+ iChildEntityMaps.ResetAndDestroy();
+
+ // Check new status for transparent folders (transparent folders are
+ // loaded during root op so they need to be checked here)
+ iNodeManager->SeenInfo().DoNewCheckForTransparentChildrenL(
+ rootNode );
+
+ iNodeManager->SeenInfo().RefreshFolderSeenStatusL( *iRootNodeIdentifier );
+
+ if ( iPendingMessage && iLoadedNodes.Count() > 0 )
+ {
+ DLINFO(("Pending message loaded nodes"));
+ // send updated nodes identifiers to proxy
+ User::LeaveIfError( CompleteMessage( iPendingMessage,
+ ENCDOperationMessageCompletionNodesUpdated,
+ iProgress,
+ iLoadedNodes,
+ KErrNone ) );
+
+ iLoadedNodes.ResetAndDestroy();
+ }
+ else if ( iPendingMessage )
+ {
+ DLINFO(("Pending message"));
+ if ( iError == KErrNone )
+ {
+ // Send complete message to proxy.
+ User::LeaveIfError( CNcdBaseOperation::CompleteMessage( iPendingMessage,
+ ENCDOperationMessageCompletionComplete,
+ iProgress,
+ KErrNone ) );
+
+ iOperationState = EStateComplete;
+ }
+ else
+ {
+ iRootNodeState = EFailed;
+ RunOperation();
+ }
+ }
+ DLTRACE((_L("->EComplete done")));
+ break;
+ }
+
+ case EFailed:
+ {
+ DLTRACE((_L("->EFailed")));
+ Cancel();
+ // Send error message in case didn't have any pending
+ // messages when the operation actually failed
+ if( iPendingMessage )
+ {
+ DLINFO(("Pending"));
+ // ignoring error because operation already failed
+ CNcdBaseOperation::CompleteMessage( iPendingMessage,
+ ENCDOperationMessageCompletionError, iError );
+ }
+ DLTRACE((_L("->EFailed done")));
+ break;
+ }
+ default:
+ {
+ DLTRACE(("default"));
+ DASSERT(0);
+ break;
+ }
+ }
+ }
+
+void CNcdLoadRootNodeOperation::ChangeToPreviousStateL()
+ {
+ DLTRACEIN(("no implementation needed"));
+ }
+
+TBool CNcdLoadRootNodeOperation::QueryCompletedL( CNcdQuery* aQuery )
+ {
+ DLTRACEIN((""));
+ TBool handled = EFalse;
+ if ( aQuery == iConfQuery )
+ {
+ // handle conf query
+ DASSERT( iRootNodeState == EConfQuery );
+ //RunOperation();
+ // Query has been handled, release it
+ /*iConfQuery->Release();
+ iConfQuery = NULL;*/
+ if ( aQuery->Response() == MNcdQuery::ERejected )
+ {
+ Cancel();
+ }
+
+ handled = ETrue;
+ }
+ else
+ {
+ // handle child ops's querys
+ TBool found = EFalse;
+ for( TInt i = 0 ; i < iSubOps.Count() ; i++ )
+ {
+ CNcdQuery* query = iSubOps[i]->ActiveQuery();
+ if ( aQuery == query )
+ {
+ iSubOps[i]->QueryHandledL( aQuery );
+ TInt index = iSubOpQuerys.Find( aQuery );
+ if ( index != KErrNotFound )
+ {
+ // remove reference
+ iSubOpQuerys[index]->InternalRelease();
+ iSubOpQuerys.Remove( index );
+ }
+ query->InternalRelease();
+ query = NULL;
+ found = ETrue;
+ break;
+ }
+ if ( query )
+ {
+ query->InternalRelease();
+ }
+ }
+ if ( !found )
+ {
+ DLINFO(("Query doesn't belong to any sub op! ERROR!"))
+ DASSERT( 0 );
+ User::Leave( KErrArgument );
+ }
+ else
+ {
+ handled = ETrue;
+ }
+ }
+ return handled;
+ }