ncdengine/provider/server/src/ncdsubscriptionoperationimpl.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <s32mem.h>
       
    20 #include <apmstd.h>
       
    21 
       
    22 #include "ncdsubscriptionoperationimpl.h"
       
    23 #include "catalogsbasemessage.h"
       
    24 #include "catalogshttpincludes.h"
       
    25 #include "ncdsubscriptionmanagerimpl.h"
       
    26 #include "catalogsutils.h"
       
    27 #include "catalogscontext.h"
       
    28 #include "ncdproviderdefines.h"
       
    29 #include "ncddescriptordownloadsuboperation.h"
       
    30 #include "ncdrequestmanagesubscriptions.h"
       
    31 #include "ncdrequestgenerator.h"
       
    32 #include "ncdrequestconfigurationdata.h"
       
    33 #include "ncdprotocol.h"
       
    34 #include "ncdparser.h"
       
    35 #include "ncdprotocoldefaultobserver.h"
       
    36 #include "ncd_pp_error.h"
       
    37 #include "ncd_pp_subscription.h"
       
    38 #include "ncdsubscriptionimpl.h"
       
    39 #include "ncdpurchaseoperationimpl.h"
       
    40 #include "ncdsubscriptiongroup.h"
       
    41 #include "ncdnodeidentifier.h"
       
    42 #include "ncdserverdetails.h"
       
    43 #include "ncdconfigurationmanager.h"
       
    44 #include "ncdcapabilities.h"
       
    45 #include "ncderrors.h"
       
    46 #include "ncdsessionhandler.h"
       
    47 #include "ncdproviderutils.h"
       
    48 #include "ncdhttputils.h"
       
    49 #include "ncdgeneralmanager.h"
       
    50 
       
    51 #include "catalogsdebug.h"
       
    52 
       
    53 
       
    54 // ======== MEMBER FUNCTIONS ========
       
    55 
       
    56 // ---------------------------------------------------------------------------
       
    57 // NewL
       
    58 // ---------------------------------------------------------------------------
       
    59 //
       
    60 CNcdSubscriptionOperation* CNcdSubscriptionOperation::NewL( 
       
    61     MNcdSubscriptionOperation::TType aSubscriptionOperationType,   
       
    62     CNcdGeneralManager& aGeneralManager,
       
    63     CNcdSubscriptionManager& aSubscriptionManager,        
       
    64     MCatalogsHttpSession& aHttpSession,    
       
    65     MNcdOperationRemoveHandler& aRemoveHandler,
       
    66     MCatalogsSession& aSession )
       
    67     {
       
    68     CNcdSubscriptionOperation* self = CNcdSubscriptionOperation::NewLC(
       
    69         aSubscriptionOperationType,
       
    70         aGeneralManager,
       
    71         aSubscriptionManager,
       
    72         aHttpSession,
       
    73         aRemoveHandler,
       
    74         aSession );
       
    75     CleanupStack::Pop( self );
       
    76     return self;
       
    77     }
       
    78 
       
    79 // ---------------------------------------------------------------------------
       
    80 // NewLC
       
    81 // ---------------------------------------------------------------------------
       
    82 //
       
    83 CNcdSubscriptionOperation* CNcdSubscriptionOperation::NewLC( 
       
    84     MNcdSubscriptionOperation::TType aSubscriptionOperationType,
       
    85     CNcdGeneralManager& aGeneralManager,
       
    86     CNcdSubscriptionManager& aSubscriptionManager,
       
    87     MCatalogsHttpSession& aHttpSession,
       
    88     MNcdOperationRemoveHandler& aRemoveHandler,
       
    89     MCatalogsSession& aSession )
       
    90     {
       
    91     CNcdSubscriptionOperation* self =
       
    92         new( ELeave ) CNcdSubscriptionOperation( 
       
    93             aSubscriptionOperationType,
       
    94             aGeneralManager,
       
    95             aSubscriptionManager,
       
    96             aHttpSession,
       
    97             aRemoveHandler,
       
    98             aSession );
       
    99     CleanupClosePushL( *self );
       
   100     self->ConstructL( NULL, KNullDesC, KNullDesC, KNullDesC, KNullDesC );
       
   101     return self;
       
   102     }
       
   103     
       
   104 
       
   105 // ---------------------------------------------------------------------------
       
   106 // NewL
       
   107 // ---------------------------------------------------------------------------
       
   108 //
       
   109 CNcdSubscriptionOperation* CNcdSubscriptionOperation::NewL(
       
   110     MNcdSubscriptionOperation::TType aSubscriptionOperationType,
       
   111     const TDesC& aPurchaseOptionId,
       
   112     const TDesC& aEntityId,
       
   113     const TDesC& aNamespace,
       
   114     const TDesC& aServerUri,
       
   115     CNcdGeneralManager& aGeneralManager,
       
   116     CNcdSubscriptionManager& aSubscriptionManager,
       
   117     MCatalogsHttpSession& aHttpSession,
       
   118     MNcdOperationRemoveHandler& aRemoveHandler,
       
   119     MCatalogsSession& aSession )
       
   120     {
       
   121     CNcdSubscriptionOperation* self = CNcdSubscriptionOperation::NewLC(
       
   122         aSubscriptionOperationType,
       
   123         aPurchaseOptionId,
       
   124         aEntityId,
       
   125         aNamespace,
       
   126         aServerUri,
       
   127         aGeneralManager,
       
   128         aSubscriptionManager,
       
   129         aHttpSession,
       
   130         aRemoveHandler,
       
   131         aSession );
       
   132     CleanupStack::Pop( self );
       
   133     return self;
       
   134     }
       
   135 
       
   136 // ---------------------------------------------------------------------------
       
   137 // NewLC
       
   138 // ---------------------------------------------------------------------------
       
   139 //
       
   140 CNcdSubscriptionOperation* CNcdSubscriptionOperation::NewLC(
       
   141     MNcdSubscriptionOperation::TType aSubscriptionOperationType,
       
   142     const TDesC& aPurchaseOptionId,
       
   143     const TDesC& aEntityId,
       
   144     const TDesC& aNamespace,
       
   145     const TDesC& aServerUri,
       
   146     CNcdGeneralManager& aGeneralManager,
       
   147     CNcdSubscriptionManager& aSubscriptionManager,
       
   148     MCatalogsHttpSession& aHttpSession,
       
   149     MNcdOperationRemoveHandler& aRemoveHandler,
       
   150     MCatalogsSession& aSession )
       
   151     {
       
   152     CNcdSubscriptionOperation* self =
       
   153         new( ELeave ) CNcdSubscriptionOperation( 
       
   154             aSubscriptionOperationType,
       
   155             aGeneralManager,
       
   156             aSubscriptionManager,
       
   157             aHttpSession,
       
   158             aRemoveHandler,
       
   159             aSession );
       
   160     CleanupClosePushL( *self );
       
   161     self->ConstructL(
       
   162         NULL,
       
   163         aPurchaseOptionId,
       
   164         aEntityId,
       
   165         aNamespace,
       
   166         aServerUri );
       
   167     return self;
       
   168     }
       
   169 
       
   170 // ---------------------------------------------------------------------------
       
   171 // Destructor
       
   172 // ---------------------------------------------------------------------------
       
   173 //
       
   174 CNcdSubscriptionOperation::~CNcdSubscriptionOperation()
       
   175     {
       
   176     DLTRACEIN((""));    
       
   177 
       
   178     DLTRACE(("Closing suboperations"));
       
   179     // Close operations
       
   180     for ( TInt i = 0; i < iSubOps.Count(); i++ )
       
   181         {
       
   182         iSubOps[i]->Close();        
       
   183         }
       
   184                 
       
   185     DLTRACE(("Suboperations closed"));
       
   186     iSubOps.Reset();
       
   187     iFailedSubOps.Reset();
       
   188     iCompletedSubOps.Reset();
       
   189 
       
   190     if ( iTransaction )
       
   191         {
       
   192         iTransaction->Release();
       
   193         iTransaction = NULL;
       
   194         }
       
   195 
       
   196     iServersSubscriptions.ResetAndDestroy();
       
   197 
       
   198     delete iSource;
       
   199     delete iPurchaseOptionId;
       
   200     delete iEntityId;
       
   201     delete iNamespace;
       
   202     delete iServerUri;
       
   203 
       
   204     delete iParser;
       
   205 
       
   206     DLTRACEOUT((""));
       
   207     }
       
   208 
       
   209 
       
   210 TInt CNcdSubscriptionOperation::RunOperation()
       
   211     {
       
   212     DLTRACEIN(( "Pending message: %X", iPendingMessage ));
       
   213 
       
   214     // Cannot determine from iOperationState whether we are
       
   215     // just starting this operation or continuing it after
       
   216     // for example expiration info has been handled.
       
   217     // This is because iOperationState will be EStateRunning
       
   218     // In both cases. This is why we use our own internal
       
   219     // variable.
       
   220     if ( iSubscriptionOperationState == EBegin )
       
   221         {
       
   222         // Operation is being started and we come here for
       
   223         // the first time
       
   224         iSubscriptionOperationState = ERunning;
       
   225         }
       
   226     else if ( iSubscriptionOperationState == EComplete )
       
   227         {
       
   228         // It is possible that the operation has completed while we have
       
   229         // been processing for example expired nodes. So we send completion
       
   230         // message immediately.
       
   231         if ( iPendingMessage )
       
   232             {
       
   233             return CompletePendingMessage();
       
   234             }
       
   235         return KErrGeneral;
       
   236         }    
       
   237     else if ( iSubscriptionOperationState == EHandlingQueries ) 
       
   238         {
       
   239         DLTRACE(("Queries handled"));
       
   240         SubscriptionOperationComplete( iError );        
       
   241         }
       
   242     else
       
   243         {
       
   244         // We don't want to start the operation again as it
       
   245         // is already running. Something should eventually trigger
       
   246         // completion of iMessage
       
   247         return KErrNone;
       
   248         }
       
   249 
       
   250     TRAPD( err,
       
   251         {
       
   252         switch ( iSubscriptionOperationType ) 
       
   253             {
       
   254             case MNcdSubscriptionOperation::EUnsubscribe:
       
   255                 RunUnsubscribeOperationL();
       
   256                 break;
       
   257             case MNcdSubscriptionOperation::ERefreshSubscriptions:
       
   258                 RunRefreshOperationL();
       
   259                 break;
       
   260             default:            
       
   261                 User::Leave( KErrNotSupported );
       
   262                 break;
       
   263             }
       
   264         } );
       
   265 
       
   266     if ( err != KErrNone )
       
   267         {
       
   268         SubscriptionOperationComplete( err );
       
   269         }
       
   270 
       
   271     DLTRACEOUT(("err: %d", err));
       
   272     return err;
       
   273     }
       
   274 
       
   275 void CNcdSubscriptionOperation::Cancel()
       
   276     {
       
   277     DLTRACEIN( ( "" ) );
       
   278 
       
   279     if ( iTransaction )
       
   280         {
       
   281         iTransaction->Cancel();
       
   282         iTransaction = NULL;
       
   283         }
       
   284     if ( iParser )
       
   285         {
       
   286         iParser->CancelParsing();
       
   287         //delete iParser;
       
   288         //iParser = NULL;
       
   289         }
       
   290         
       
   291     CancelSuboperations();            
       
   292 
       
   293     DLTRACEOUT(( "" ));
       
   294     }
       
   295     
       
   296 
       
   297 TBool CNcdSubscriptionOperation::QueryCompletedL( CNcdQuery* /* aQuery */ )
       
   298     {
       
   299     DLTRACEIN((""));
       
   300     return EFalse;
       
   301     }
       
   302     
       
   303 
       
   304 void CNcdSubscriptionOperation::HandleHttpEventL( 
       
   305         MCatalogsHttpOperation& aOperation, 
       
   306         TCatalogsHttpEvent aEvent )
       
   307     {
       
   308     DLTRACEIN((""));
       
   309     DASSERT( &aOperation == iTransaction );
       
   310     DASSERT( aOperation.OperationType() == ECatalogsHttpTransaction );
       
   311 
       
   312     TCatalogsTransportProgress progress( iTransaction->Progress() );
       
   313     
       
   314     switch( aEvent.iOperationState ) 
       
   315         {
       
   316         // Handle completed operation
       
   317         case ECatalogsHttpOpCompleted:
       
   318             {
       
   319             // Inform parser that no more data will be sent
       
   320             iParser->EndL();
       
   321             break;
       
   322             }        
       
   323         // Handle operation in progress
       
   324         case ECatalogsHttpOpInProgress:
       
   325             {
       
   326             if( aEvent.iProgressState == ECatalogsHttpResponseBodyReceived )
       
   327                 {
       
   328                 // send received data to parser
       
   329                 iParser->ParseL( aOperation.Body() );
       
   330                 }      
       
   331             break;
       
   332             }
       
   333                     
       
   334         default:
       
   335             {
       
   336             break;
       
   337             }
       
   338         }
       
   339         
       
   340     DLTRACEOUT((""));    
       
   341     }
       
   342 
       
   343 TBool CNcdSubscriptionOperation::HandleHttpError(
       
   344         MCatalogsHttpOperation& aOperation,
       
   345         TCatalogsHttpError aError )
       
   346     {
       
   347     DLTRACEIN(("Error type: %d, code: %d", aError.iType, aError.iError ));    
       
   348     
       
   349     DASSERT( &aOperation == iTransaction );
       
   350     
       
   351     aOperation.Release();
       
   352     iTransaction = NULL;
       
   353 
       
   354     SubscriptionOperationComplete( aError.iError );
       
   355         
       
   356     DLTRACEOUT((""));
       
   357     return ETrue;
       
   358     }
       
   359 
       
   360 void CNcdSubscriptionOperation::ParseError( TInt aErrorCode )
       
   361     {
       
   362     DLTRACEIN(("error:%d", aErrorCode ));
       
   363 
       
   364     // Handle error only if operation is not completed already
       
   365     // (cancellation of parsing may cause an unnecessary call to this function).
       
   366     if ( iSubscriptionOperationState != EComplete )
       
   367         {
       
   368             if ( iTransaction )
       
   369             {
       
   370             iTransaction->Cancel();        
       
   371             iTransaction = NULL;
       
   372             }
       
   373 
       
   374         SubscriptionOperationComplete( aErrorCode );
       
   375 
       
   376         }
       
   377     
       
   378     DLTRACEOUT((""));
       
   379     }
       
   380 
       
   381 void CNcdSubscriptionOperation::ParseCompleteL( TInt aError )
       
   382     {
       
   383     DLTRACEIN((_L("error:%d"), aError ));
       
   384 
       
   385     if ( iParser )
       
   386         {
       
   387         delete iParser;
       
   388         iParser = NULL;
       
   389         }
       
   390 
       
   391     // HandleQuerysL will continue the operation in RunOperation
       
   392     iSubscriptionOperationState = EHandlingQueries;
       
   393     iError = aError;
       
   394     HandleQuerysL();
       
   395 
       
   396     DLTRACEOUT((""));
       
   397     }
       
   398 
       
   399 void CNcdSubscriptionOperation::ValidSubscriptionL(
       
   400     MNcdPreminetProtocolSubscription* aData )
       
   401     {
       
   402     DLTRACEIN((""));
       
   403 
       
   404     iServersSubscriptions.AppendL( aData );
       
   405 
       
   406     DLTRACEOUT((""));
       
   407     }
       
   408 
       
   409 void CNcdSubscriptionOperation::OldSubscriptionL(
       
   410     MNcdPreminetProtocolSubscription* aData )
       
   411     {
       
   412     DLTRACEIN((""));
       
   413 
       
   414     iServersSubscriptions.AppendL( aData );
       
   415 
       
   416     DLTRACEOUT((""));
       
   417     }
       
   418 
       
   419 
       
   420 void CNcdSubscriptionOperation::Progress( CNcdBaseOperation& /*aOperation*/ )
       
   421     {
       
   422     DLTRACEIN((""));
       
   423     DLTRACEOUT((""));
       
   424     }
       
   425 
       
   426 void CNcdSubscriptionOperation::QueryReceived( CNcdBaseOperation& /*aOperation*/,
       
   427                                 CNcdQuery* /*aQuery*/ )
       
   428     {
       
   429     DLTRACEIN((""));
       
   430     DLTRACEOUT((""));
       
   431     }
       
   432 
       
   433 void CNcdSubscriptionOperation::OperationComplete(
       
   434     CNcdBaseOperation* aOperation,
       
   435     TInt aError )
       
   436     {
       
   437     DLTRACEIN(("error=%d", aError));
       
   438 
       
   439     if ( iSubscriptionOperationType == MNcdSubscriptionOperation::EUnsubscribe )
       
   440         {
       
   441         SubscriptionOperationComplete( aError );
       
   442         }
       
   443     else if ( iSubscriptionOperationType ==
       
   444         MNcdSubscriptionOperation::ERefreshSubscriptions )
       
   445         {
       
   446         DLINFO(("Refresh subscription op complete."));
       
   447         
       
   448         TRAPD( err,
       
   449             {
       
   450             CNcdSubscriptionOperation* subOp =
       
   451                 static_cast<CNcdSubscriptionOperation*>( aOperation );
       
   452                 
       
   453             if ( aError != KErrNone )
       
   454                 {
       
   455                 DLINFO(("Refresh sub operation failed."));
       
   456                 iFailedSubOps.AppendL( subOp );
       
   457                 if ( iCompletionErrorCode == KErrNone )
       
   458                     {
       
   459                     iCompletionErrorCode = aError;
       
   460                     }
       
   461                 }
       
   462             else
       
   463                 {
       
   464                 DLINFO(("Refresh sub operation successfull."));
       
   465                 iCompletedSubOps.AppendL( subOp );
       
   466                 }
       
   467             } ); //TRAPD
       
   468 
       
   469         if ( err != KErrNone )
       
   470             {
       
   471             DLERROR(("Internal subscription operation error"));
       
   472             SubscriptionOperationComplete( err );
       
   473             }
       
   474         else if ( iFailedSubOps.Count() + iCompletedSubOps.Count() ==
       
   475             iSubOps.Count() )
       
   476             {
       
   477             // All sub operations completed, the operation is complete.
       
   478             if ( iFailedSubOps.Count() && iCompletedSubOps.Count() )
       
   479                 {
       
   480                 // Some suboperations has failed, but not all.
       
   481                 SubscriptionOperationComplete( KNcdErrorSomeSubscriptionsFailedToUpdate );
       
   482                 }
       
   483             else if ( iFailedSubOps.Count() )
       
   484                 {
       
   485                 // All suboperations has failed.
       
   486                 SubscriptionOperationComplete( iCompletionErrorCode );
       
   487                 }
       
   488             else
       
   489                 {                
       
   490                 SubscriptionOperationComplete( KErrNone );
       
   491                 }
       
   492             }
       
   493         }
       
   494 
       
   495     DLTRACEOUT((""));
       
   496     }
       
   497 
       
   498 void CNcdSubscriptionOperation::ErrorL( MNcdPreminetProtocolError* aData )
       
   499     {
       
   500     DLTRACEIN((""));
       
   501 
       
   502     CleanupDeletePushL( aData );
       
   503 
       
   504     // Map error codes to correct enumeration values.
       
   505     switch ( aData->Code() ) 
       
   506         {
       
   507         case 404:
       
   508             {
       
   509             iError = KNcdErrorNotFound;
       
   510             DASSERT( iSubscription );
       
   511             if ( iSubscription )
       
   512                 {
       
   513                 RemoveSubscriptionL( *iSubscription );
       
   514                 iSubscription = NULL;
       
   515                 }                        
       
   516             break;
       
   517             }
       
   518         case 416:
       
   519             {
       
   520             DLTRACE(("session expired"));
       
   521             Cancel();
       
   522             
       
   523             switch ( iSubscriptionOperationType ) 
       
   524                 {
       
   525                 case MNcdSubscriptionOperation::EUnsubscribe:
       
   526                     {
       
   527                     iProtocol.SessionHandlerL( iSession.Context() ).
       
   528                         RemoveSession( *iServerUri, *iNamespace );
       
   529                     break;
       
   530                     }
       
   531                 case MNcdSubscriptionOperation::ERefreshSubscriptions:
       
   532                     {
       
   533                     iProtocol.SessionHandlerL( iSession.Context() ).
       
   534                         RemoveSession( iSource->Uri(), iSource->Namespace() );
       
   535                     break;
       
   536                     }                    
       
   537                 default:            
       
   538                     DASSERT(0);
       
   539                     break;
       
   540                 }
       
   541             
       
   542             DLINFO(("Start operation from the beginning"));            
       
   543             // continue operation asynchronously to prevent problems with parser
       
   544             ContinueOperationL();
       
   545             break;
       
   546             }
       
   547         case 426:
       
   548             iError = KNcdErrorSubscriptionPaymentAlreadyDone;
       
   549             break;
       
   550         case 427:
       
   551             iError = KNcdErrorSubscriptionNotSubscribed;
       
   552             DASSERT( iSubscription );
       
   553             if ( iSubscription )
       
   554                 {
       
   555                 RemoveSubscriptionL( *iSubscription );
       
   556                 iSubscription = NULL;
       
   557                 }  
       
   558             break;
       
   559         case 428:
       
   560             iError = KNcdErrorSubscriptionInvalid;
       
   561             DASSERT( iSubscription );
       
   562             if ( iSubscription )
       
   563                 {
       
   564                 RemoveSubscriptionL( *iSubscription );
       
   565                 iSubscription = NULL;
       
   566                 }  
       
   567             break;
       
   568         case 429:
       
   569             iError = KNcdErrorSubscriptionNotEnoughCredits;
       
   570             break;
       
   571         default:
       
   572             iError = KNcdProtocolErrorBase - aData->Code();
       
   573             break;
       
   574         }
       
   575 
       
   576     //CNcdBaseOperation::ErrorL( aData );        
       
   577 
       
   578     // Default observer deletes the data.
       
   579     CleanupStack::Pop( aData );
       
   580 
       
   581     iParser->DefaultObserver().ErrorL( aData );
       
   582     
       
   583     if( iError != KErrNone )
       
   584         {
       
   585         SubscriptionOperationComplete( iError );
       
   586         }    
       
   587 
       
   588     DLTRACEOUT((""));
       
   589     }
       
   590     
       
   591 void CNcdSubscriptionOperation::SubscriptionsInternalizeComplete(
       
   592     TInt /*aError*/ )
       
   593     {
       
   594     DLTRACEIN((""));
       
   595     
       
   596     // call observers
       
   597     DLINFO(("Calling observers."));
       
   598     for ( TInt i = 0 ; i < iObservers.Count() ; i++ )
       
   599         {
       
   600         DLINFO(("Calling observer: %d .", i ));
       
   601         iObservers[i]->OperationComplete( this, KErrNone );
       
   602         }
       
   603     }
       
   604 
       
   605 CNcdSubscriptionOperation* CNcdSubscriptionOperation::CreateSubOperationLC(
       
   606     CNcdSubscriptionsSourceIdentifier* aSource,
       
   607     CNcdGeneralManager& aGeneralManager,
       
   608     CNcdSubscriptionManager& aSubscriptionManager,    
       
   609     MCatalogsHttpSession& aHttpSession,
       
   610     MNcdOperationRemoveHandler& aRemoveHandler,
       
   611     MCatalogsSession& aSession )
       
   612     {
       
   613     CNcdSubscriptionOperation* self =
       
   614         new( ELeave ) CNcdSubscriptionOperation( 
       
   615             MNcdSubscriptionOperation::ERefreshSubscriptions,
       
   616             aGeneralManager,
       
   617             aSubscriptionManager,
       
   618             aHttpSession,
       
   619             aRemoveHandler,
       
   620             aSession );
       
   621     CleanupClosePushL( *self );
       
   622     self->ConstructL( aSource, KNullDesC, KNullDesC, KNullDesC, KNullDesC );
       
   623     return self;
       
   624     }
       
   625 
       
   626 void CNcdSubscriptionOperation::RunRefreshOperationL()
       
   627     {
       
   628     DLTRACEIN((""));
       
   629 
       
   630     if ( iSource )
       
   631         {
       
   632         DLTRACE(( "Sub operation" ));
       
   633         // This is a sub operation. Send request to the given source.
       
   634 
       
   635         CNcdRequestManageSubscriptions* request =
       
   636             NcdRequestGenerator::CreateManageSubscriptionsRequestLC();
       
   637 
       
   638         // Set namespace from the source.
       
   639         request->SetNamespaceL( iSource->Namespace() );
       
   640 
       
   641         MCatalogsContext& context( iSession.Context() );
       
   642 
       
   643         HBufC8* data =
       
   644             iProtocol.ProcessPreminetRequestL(
       
   645                 context,
       
   646                 *request,
       
   647                 iSource->Uri() );
       
   648 
       
   649         CleanupStack::PopAndDestroy( request );
       
   650         CleanupStack::PushL( data );
       
   651 
       
   652         // create transaction
       
   653         iGeneralManager.HttpUtils().CreateTransactionL(
       
   654             iHttpSession,
       
   655             iTransaction,
       
   656             iSource->Uri(),
       
   657             *this,
       
   658             *data,
       
   659             iSource->Namespace(),
       
   660             MCatalogsAccessPointManager::EBrowse,
       
   661             iClientUid );
       
   662         
       
   663         CleanupStack::PopAndDestroy( data );
       
   664         
       
   665         // create parser  
       
   666         delete iParser;
       
   667         iParser = NULL;
       
   668         iParser = iProtocol.CreateParserL( context, iSource->Uri() );
       
   669 
       
   670         // Set observers
       
   671         MNcdParserObserverBundle& observers = iParser->Observers();
       
   672         observers.SetParserObserver( this );
       
   673         observers.SetSubscriptionObserver( this );
       
   674         observers.SetInformationObserver( this );
       
   675         observers.SetErrorObserver( this );
       
   676 
       
   677         iParser->BeginAsyncL();
       
   678 
       
   679         // start transaction
       
   680         User::LeaveIfError( iTransaction->Start() );
       
   681         }
       
   682     else
       
   683         {
       
   684         DLTRACE(( "Main operation" ));
       
   685         // This is the main operation. Sub operations are started
       
   686         // from here.
       
   687 
       
   688         // Get sources for sub operations.
       
   689         RPointerArray<CNcdSubscriptionsSourceIdentifier> sources =
       
   690             iSubscriptionManager.SubscriptionsSourcesL(
       
   691                 iClientUid );
       
   692         CleanupResetAndDestroyPushL( sources );
       
   693         
       
   694         TInt count = sources.Count();
       
   695         
       
   696         DLTRACE(( "Source count: %d", count ));
       
   697         
       
   698         if ( count == 0 )
       
   699             {
       
   700             // No sources found.
       
   701             CleanupStack::PopAndDestroy( &sources );
       
   702             
       
   703             SubscriptionOperationComplete( KErrNone );
       
   704 
       
   705             DLTRACEOUT((""));
       
   706             return;
       
   707             }
       
   708 
       
   709         // Start all sub operations.
       
   710         for ( TInt i = 0; i < count; i++ )
       
   711             {
       
   712             DLTRACE(( _L("Source URI: %S"), &sources[0]->Uri() ));
       
   713             DLTRACE(( _L("Source namespace: %S"), &sources[0]->Namespace() ));
       
   714 
       
   715             const MCatalogsContext& context( iSession.Context() );
       
   716             MNcdServerDetails& serverDetails =
       
   717                 iConfigurationManager.ServerDetailsL(
       
   718                     context,
       
   719                     sources[0]->Uri(),
       
   720                     sources[0]->Namespace() );
       
   721 
       
   722             // Capabilities are checked only if it is required
       
   723             if ( sources[0]->RequiresCapabilityCheck() &&
       
   724                      serverDetails.IsCapabilitySupported(
       
   725                          NcdCapabilities::KSubscriptions )
       
   726                  || !sources[0]->RequiresCapabilityCheck() )
       
   727                 {
       
   728                 DLTRACE(( "This source supports subscriptions!" ));
       
   729                 DLINFO(( "Capability check was required: %d",
       
   730                          sources[0]->RequiresCapabilityCheck() ));
       
   731 
       
   732                 CNcdSubscriptionOperation* subOp =
       
   733                     CNcdSubscriptionOperation::CreateSubOperationLC(
       
   734                         sources[0],
       
   735                         iGeneralManager,
       
   736                         iSubscriptionManager,
       
   737                         iHttpSession,
       
   738                         *iRemoveHandler,
       
   739                         iSession );
       
   740                 // CreateSubOperationLC takes the ownership of the first
       
   741                 // object in the sources array. Remove it from sources.
       
   742                 sources.Remove( 0 );
       
   743                 subOp->AddObserverL( this );
       
   744                 User::LeaveIfError( subOp->Start() );
       
   745                 DLTRACE(( "Sub operation started!" ));
       
   746                 iSubOps.AppendL( subOp );
       
   747                 CleanupStack::Pop( subOp );
       
   748                 }
       
   749             else
       
   750                 {
       
   751                 DLTRACE(( "This source does not support subscriptions!" ));
       
   752 
       
   753                 // Do not use this source.
       
   754                 sources.Remove( 0 );
       
   755                 }
       
   756             }
       
   757 
       
   758         CleanupStack::PopAndDestroy( &sources );
       
   759 
       
   760         // Any sub operations started
       
   761         if ( iSubOps.Count() == 0 )
       
   762             {
       
   763             DLTRACE(( "None of the sources did not support subscriptions!" ));
       
   764             SubscriptionOperationComplete( KErrNone );
       
   765             }
       
   766         }
       
   767 
       
   768     DLTRACEOUT((""));
       
   769     }
       
   770     
       
   771     
       
   772 void CNcdSubscriptionOperation::RunUnsubscribeOperationL()
       
   773     {
       
   774     DLTRACEIN((""));
       
   775 
       
   776     CNcdRequestManageSubscriptions* request =
       
   777         NcdRequestGenerator::CreateManageSubscriptionsRequestLC();
       
   778 
       
   779     request->SetNamespaceL( *iNamespace );
       
   780     request->AddSubscriptionL(
       
   781         *iEntityId,
       
   782         *iPurchaseOptionId,
       
   783         EUnsubscribe );
       
   784 
       
   785     MCatalogsContext& context( iSession.Context() );
       
   786 
       
   787     HBufC8* data =
       
   788         iProtocol.ProcessPreminetRequestL(
       
   789             context,
       
   790             *request,
       
   791             *iServerUri );
       
   792 
       
   793     CleanupStack::PopAndDestroy( request );
       
   794     CleanupStack::PushL( data );
       
   795 
       
   796     // create transaction
       
   797     iGeneralManager.HttpUtils().CreateTransactionL(
       
   798         iHttpSession,
       
   799         iTransaction,
       
   800         *iServerUri,
       
   801         *this,
       
   802         *data,
       
   803         *iNamespace,
       
   804         MCatalogsAccessPointManager::EBrowse,
       
   805         iClientUid );
       
   806         
       
   807     CleanupStack::PopAndDestroy( data );
       
   808             
       
   809     // create parser  
       
   810     delete iParser;
       
   811     iParser = NULL;
       
   812     iParser = iProtocol.CreateParserL( context, *iServerUri );
       
   813 
       
   814     // Set observers
       
   815     MNcdParserObserverBundle& observers = iParser->Observers();
       
   816     observers.SetParserObserver( this );
       
   817     observers.SetSubscriptionObserver( this );
       
   818     observers.SetInformationObserver( this );
       
   819     observers.SetErrorObserver( this );
       
   820 
       
   821     iParser->BeginAsyncL();
       
   822 
       
   823     // start transaction
       
   824     User::LeaveIfError( iTransaction->Start() );
       
   825 
       
   826     DLTRACEOUT((""));
       
   827     }
       
   828 
       
   829 TInt CNcdSubscriptionOperation::SubscriptionOperationComplete( TInt aError )
       
   830     {
       
   831     DLTRACEIN((""));
       
   832 
       
   833     // iSubscriptionOperationState is used in RunOperation to determine
       
   834     // whether this operation has already completed (this function has been
       
   835     // called).
       
   836     // We should complete incoming message in RunOperation if it was not
       
   837     // available in this function.
       
   838     
       
   839     // Notice that we cannot automatically set iOperationState to be
       
   840     // EStateComplete as iOperationState is used when we receive
       
   841     // continue message. State EStateComplete would produce an error in that
       
   842     // case because it means that we are not waiting any messages anymore.
       
   843     // This is why we have to use two state variables to inform of completion.
       
   844     
       
   845     iSubscriptionOperationState = EComplete;
       
   846 
       
   847     // Also given error code has to be stored if iPendingMessage is not
       
   848     // currently available    
       
   849     iCompletionErrorCode = aError; 
       
   850 
       
   851 
       
   852     if ( aError != KErrNone )
       
   853         {
       
   854         DLTRACE((_L("->Operation failed")));
       
   855         // Operation failed, send error message.
       
   856         Cancel();
       
   857         if ( iPendingMessage )
       
   858             {
       
   859             CompletePendingMessage();
       
   860             }
       
   861         // call observers
       
   862         for ( TInt i = 0 ; i < iObservers.Count() ; i++ )
       
   863             {
       
   864             iObservers[i]->OperationComplete( this, aError );
       
   865             }
       
   866         }
       
   867     else
       
   868         {
       
   869         DLTRACE((_L("->Operation complete")));
       
   870         // Operation has completed.
       
   871 
       
   872         if ( iPendingMessage )
       
   873             {
       
   874             TInt err = CompletePendingMessage();
       
   875             if ( err != KErrNone )
       
   876                 {
       
   877                 // call observers
       
   878                 for ( TInt i = 0 ; i < iObservers.Count() ; i++ )
       
   879                     {
       
   880                     iObservers[i]->OperationComplete( this, aError );
       
   881                     }
       
   882                 return err;
       
   883                 }
       
   884             }
       
   885         
       
   886         TInt err = KErrNone;
       
   887         if ( iSource && iSubscriptionOperationType ==
       
   888             MNcdSubscriptionOperation::ERefreshSubscriptions )
       
   889             {
       
   890             TRAP_IGNORE(
       
   891                 {
       
   892                 iSubscriptionManager.InternalizeSubscriptionsFromServerL(
       
   893                     iClientUid,
       
   894                     iSource->Uri(),
       
   895                     iServersSubscriptions,
       
   896                     &iSession.Context(),
       
   897                     this );
       
   898                 } );
       
   899                 
       
   900             // Do not call operation complete here if this is
       
   901             // suboperation. Instead do it after internalize in
       
   902             // SubscriptionsInternalizeComplete()
       
   903             DLTRACEOUT((""));
       
   904             return KErrNone;
       
   905             }
       
   906             
       
   907         // call observers
       
   908         DLINFO(("Calling observers."));
       
   909         for ( TInt i = 0 ; i < iObservers.Count() ; i++ )
       
   910             {
       
   911             DLINFO(("Calling observer: %d .", i ));
       
   912             iObservers[i]->OperationComplete( this, err );
       
   913             }
       
   914         }
       
   915 
       
   916     DLTRACEOUT((""));
       
   917     return KErrNone;
       
   918     }
       
   919 
       
   920 TInt CNcdSubscriptionOperation::CompletePendingMessage()
       
   921     {
       
   922     DASSERT( iPendingMessage );
       
   923     DLTRACEIN(( "Pending message: %X", iPendingMessage ));
       
   924     
       
   925     TInt err( 0 );
       
   926     if ( iCompletionErrorCode != KErrNone )
       
   927         {
       
   928         err = CNcdBaseOperation::CompleteMessage(
       
   929                        iPendingMessage,
       
   930                        ENCDOperationMessageCompletionError,
       
   931                        iCompletionErrorCode );
       
   932         }
       
   933     else
       
   934         {
       
   935         err = CNcdBaseOperation::CompleteMessage( iPendingMessage,
       
   936             ENCDOperationMessageCompletionComplete,
       
   937             iProgress,
       
   938             KErrNone );
       
   939         }            
       
   940     // iPendingMessage = NULL set by CompleteMessage
       
   941       
       
   942     // Is this ok?
       
   943     iOperationState = EStateComplete;
       
   944     
       
   945     return err;
       
   946     }
       
   947     
       
   948 void CNcdSubscriptionOperation::RemoveSubscriptionL(
       
   949     const CNcdSubscription& aSubscription ) 
       
   950     {
       
   951     CNcdNodeIdentifier* nodeId = CNcdNodeIdentifier::NewLC(
       
   952         aSubscription.ParentGroup().Namespace(),
       
   953         aSubscription.ParentGroup().EntityId(), iClientUid );
       
   954     iSubscriptionManager.RemoveSubscriptionL(
       
   955         *nodeId, aSubscription.PurchaseOptionId() );
       
   956     CleanupStack::PopAndDestroy( nodeId );
       
   957     }
       
   958     
       
   959 
       
   960 
       
   961 void CNcdSubscriptionOperation::ChangeToPreviousStateL()
       
   962     {
       
   963     DLTRACEIN((""));
       
   964     // Nothing to do. This is needed for query handling, ResendRequestL uses this
       
   965     }
       
   966     
       
   967 void CNcdSubscriptionOperation::CancelSuboperations()
       
   968     {
       
   969     DLTRACEIN((""));
       
   970     
       
   971     for ( TInt i = 0; i < iSubOps.Count(); i++ )
       
   972         {
       
   973         CNcdSubscriptionOperation* operation = iSubOps[ i ];
       
   974         if ( iCompletedSubOps.Find( operation ) == KErrNotFound &&
       
   975              iFailedSubOps.Find( operation ) == KErrNotFound )
       
   976             {
       
   977             DLINFO(("operation not completed yet, cancel it"));
       
   978             operation->Cancel();
       
   979             }
       
   980         }
       
   981     }
       
   982 
       
   983 
       
   984 // ---------------------------------------------------------------------------
       
   985 // Constructor
       
   986 // ---------------------------------------------------------------------------
       
   987 //
       
   988 CNcdSubscriptionOperation::CNcdSubscriptionOperation(
       
   989     MNcdSubscriptionOperation::TType aSubscriptionOperationType,
       
   990     CNcdGeneralManager& aGeneralManager,
       
   991     CNcdSubscriptionManager& aSubscriptionManager,
       
   992     MCatalogsHttpSession& aHttpSession,
       
   993     MNcdOperationRemoveHandler& aRemoveHandler,
       
   994     MCatalogsSession& aSession )
       
   995     :
       
   996     CNcdBaseOperation( aGeneralManager, &aRemoveHandler, ESubscriptionOperation, aSession ),
       
   997     iSubscriptionOperationState( EBegin ),
       
   998     iSubscriptionOperationType( aSubscriptionOperationType ),
       
   999     iAccessPointManager( aGeneralManager.AccessPointManager() ),
       
  1000     iSubscriptionManager( aSubscriptionManager ),
       
  1001     iNodeManager( aGeneralManager.NodeManager() ),
       
  1002     iConfigurationManager( aGeneralManager.ConfigurationManager() ),
       
  1003     iHttpSession( aHttpSession ),
       
  1004     iProtocol( aGeneralManager.ProtocolManager() ),
       
  1005     iCompletionErrorCode( KErrNone )
       
  1006     {
       
  1007     }
       
  1008 
       
  1009 
       
  1010 // ---------------------------------------------------------------------------
       
  1011 // ConstructL
       
  1012 // ---------------------------------------------------------------------------
       
  1013 //
       
  1014 void CNcdSubscriptionOperation::ConstructL(
       
  1015     CNcdSubscriptionsSourceIdentifier* aSource,
       
  1016     const TDesC& aPurchaseOptionId,
       
  1017     const TDesC& aEntityId,
       
  1018     const TDesC& aNamespace,
       
  1019     const TDesC& aServerUri )
       
  1020 
       
  1021     {
       
  1022     DLTRACEIN(("aSource=%08x", aSource));
       
  1023 
       
  1024     // Call ConstructL for the base class
       
  1025     CNcdBaseOperation::ConstructL();
       
  1026 
       
  1027     iSource = aSource;
       
  1028     iPurchaseOptionId = aPurchaseOptionId.AllocL();
       
  1029     iEntityId = aEntityId.AllocL();
       
  1030     iNamespace = aNamespace.AllocL();
       
  1031     iServerUri = aServerUri.AllocL();
       
  1032     
       
  1033     iClientUid = iSession.Context().FamilyId();
       
  1034 
       
  1035     if ( iPurchaseOptionId->Length() > 0 &&
       
  1036         iEntityId->Length() > 0 &&
       
  1037         iNamespace->Length() > 0 )
       
  1038         {
       
  1039         iSubscription = &iSubscriptionManager.SubscriptionL(
       
  1040             *iEntityId,
       
  1041             *iNamespace,
       
  1042             *iPurchaseOptionId,
       
  1043             iClientUid );
       
  1044         }
       
  1045 
       
  1046     DLTRACEOUT((""));
       
  1047     }