xdmprotocols/XcapProtocol/src/XcapDirectory.cpp
changeset 0 c8caa15ef882
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xdmprotocols/XcapProtocol/src/XcapDirectory.cpp	Tue Feb 02 01:05:17 2010 +0200
@@ -0,0 +1,501 @@
+/*
+* Copyright (c) 2005 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: CXcapDirectory
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <utf.h>
+#include <f32file.h>
+#include "XcapAppUsageDef.h"
+#include "XdmProtocol.h"
+#include "XcapDocument.h"
+#include "XcapProtocol.h"
+#include "XcapAppUsage.h"
+#include "XcapRetrieval.h"
+#include "XcapDirectory.h"
+#include "XdmXmlParser.h"
+#include "XcapHttpReqGet.h"
+#include "XdmDocumentNode.h"
+#include "XdmNodeAttribute.h"
+#include "XcapHttpTransport.h"
+#include "XdmOperationFactory.h"
+
+// ----------------------------------------------------------
+// CXcapDirectory::CXcapDirectory
+// 
+// ----------------------------------------------------------
+//
+CXcapDirectory::CXcapDirectory( CXdmDocument*& aDirectoryDoc,
+                                CXdmEngine& aXdmEngine,
+                                CXcapProtocol& aXcapProtocol ) :
+                                CXdmDirectory( aXdmEngine ),
+                                iDirectoryDoc( ( CXcapDocument* )aDirectoryDoc ),
+                                iXcapProtocol( aXcapProtocol )                                             
+    { 
+    }
+
+// ----------------------------------------------------------
+// CXcapDirectory::NewL
+// 
+// ----------------------------------------------------------
+//
+CXcapDirectory* CXcapDirectory::NewL( const TDesC& aAUID,
+                                      CXdmEngine& aXdmEngine,
+                                      CXdmDocument*& aDirectoryDoc,
+                                      CXcapProtocol& aXcapProtocol )
+    {
+    CXcapDirectory* self = new ( ELeave ) CXcapDirectory( aDirectoryDoc, aXdmEngine, aXcapProtocol );
+    CleanupStack::PushL( self );
+    self->ConstructL( aAUID );
+    CleanupStack::Pop();
+    return self;
+    }
+
+// ----------------------------------------------------
+// CXcapDirectory::~CXcapDirectory
+// 
+// ----------------------------------------------------
+//
+CXcapDirectory::~CXcapDirectory()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDirectory::~CXcapDirectory()" ) );
+    #endif
+    Cancel();
+    delete iAUID;
+    delete iDirectoryDoc;
+    delete iHttpRetrieval;
+    iUpdateList.Close();
+    iDocumentList.Close();
+    }
+    
+// ----------------------------------------------------------
+// CXcapDirectory::ConstructL
+// 
+// ----------------------------------------------------------
+//
+void CXcapDirectory::ConstructL( const TDesC& aAUID )
+    {
+    if( aAUID.Length() > 0 )
+        {
+        _LIT( KNodePath,    "xcap-directory/folder" );
+        iAUID = HBufC::NewL( aAUID.Length() );
+        iAUID->Des().Copy( aAUID );
+        CXdmDocumentNode* node = iDirectoryDoc->DocumentSubsetL( KNodePath );
+        CleanupStack::PushL( node );
+        CXdmNodeAttribute* auid = node->CreateAttributeL( KAuidAttribute );
+        CleanupStack::PushL( auid );
+        auid->SetAttributeValueL( aAUID );
+        iDirectoryDoc->FetchDataL( node );
+        //Set the option that prohibits caching
+        iDirectoryDoc->SetOption( KXdmOption3 );
+        CleanupStack::Pop( 2 );  //auid, node
+        }
+    else iDirectoryDoc->FetchDataL();
+    CActiveScheduler::Add( this );
+    }
+
+// ----------------------------------------------------------
+// CXcapDirectory::StartUpdateL
+// 
+// ----------------------------------------------------------
+//
+void CXcapDirectory::StartUpdateL()
+    
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDirectory::StartUpdateL()" ) );
+    #endif
+    switch( iUpdatePhase )
+        {
+        case EDirPhaseIdle:
+            User::RequestComplete( iClientStatus, KErrArgument );
+            break;
+        case EUpdateDocumentList:
+            HandleDocumentListRequestL();
+            break;
+        case ERefreshDocuments:
+            HandleRefreshRequestL();
+            break;
+        default:
+            break;
+        } 
+    }
+
+// ----------------------------------------------------------
+// CXcapDirectory::SaveRequestData
+// 
+// ----------------------------------------------------------
+//
+void CXcapDirectory::SaveRequestData( TDirUpdatePhase aUpdatePhase,
+                                      TRequestStatus& aClientStatus )
+    {
+    iUpdatePhase = aUpdatePhase;
+    iClientStatus = &aClientStatus;
+    }
+    
+// ----------------------------------------------------
+// CXcapDirectory::HandleDocumentListRequestL
+// 
+// ----------------------------------------------------
+//
+void CXcapDirectory::HandleDocumentListRequestL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDirectory::HandleDocumentListRequestL()" ) );
+    #endif
+    if( !IsActive() )
+        {
+        CXcapDocument* doc = ( CXcapDocument* )iDirectoryDoc;
+        doc->StartInternalL( iStatus );
+        iUpdatePhase = EUpdateDocumentList;
+        SetActive();
+        }
+    }
+    
+// ----------------------------------------------------
+// CXcapDirectory::HandleRefreshRequestL
+// 
+// ----------------------------------------------------
+//
+void CXcapDirectory::HandleRefreshRequestL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDirectory::HandleRefreshRequestL()" ) );
+    #endif
+    if( iUpdatePhase == EUpdateDocumentList )
+        {
+        if( iUpdateList.Count() > 0 )
+            {
+            iUpdateIndex = -1;
+            iHttpRetrieval = iXcapProtocol.Transport().GetL( TPtrC() );
+            UpdateNextDocumentL();
+            iUpdatePhase = ERefreshDocuments;
+            }
+        else
+            {
+            #ifdef _DEBUG
+                iXcapProtocol.WriteToLog( _L8( "  All documents are up to date" ) );
+            #endif
+            User::RequestComplete( iClientStatus, KErrNone );
+            }
+        }
+    else
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( "  Wrong state [%d]" ), iUpdatePhase );
+        #endif
+        User::RequestComplete( iClientStatus, KErrNotReady );
+        }
+    }
+
+// ----------------------------------------------------
+// CXcapDirectory::UpdateNextDocumentL
+// 
+// ----------------------------------------------------
+//
+void CXcapDirectory::UpdateNextDocumentL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDirectory::UpdateNextDocumentL()" ) );
+    #endif
+    iUpdateIndex++;
+    if( iUpdateIndex < iUpdateList.Count() )
+        {
+        CXdmDocumentNode* node = iUpdateList[iUpdateIndex];
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( "  Index: %d  Document: %x" ), iUpdateIndex, node );
+        #endif
+        TPtrC8 root = iXcapProtocol.Transport().RootUri();
+        TPtrC docUri( ExtractDocumentUriL( root, node ) );
+        HBufC* uri = HBufC::NewLC( root.Length() + docUri.Length() );
+        uri->Des().Copy( root );
+        uri->Des().Append( docUri );
+        iHttpRetrieval->ResetUriL( uri->Des() );
+        iHttpRetrieval->SetExpiryTimeL( NULL, KDefaultHttpRequestTimeout * 1000000 );
+        iHttpRetrieval->DispatchRequestL( iStatus );
+        CleanupStack::PopAndDestroy();  //uri
+        SetActive();
+        }
+    else
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( "  Directory sync complete" ) );
+        #endif
+        User::RequestComplete( iClientStatus, KErrNone );
+        }
+    }
+
+// ---------------------------------------------------------
+// CXcapDirectory::RunL()
+// 
+// ---------------------------------------------------------
+//
+void CXcapDirectory::RunL()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDirectory::RunL() - Request: %d" ), iStatus.Int() );
+    #endif
+    if( iStatus == KErrNone )
+        {
+        switch( iUpdatePhase )
+            {
+            case EUpdateDocumentList:
+                {
+                iDocumentCount = iDirectoryDoc->Find( KDirectoryEntry, iDocumentList );
+                if( iDocumentCount > 0 )
+                    {
+                    TInt index = 0;
+                    while( index < iDocumentCount )
+                        {
+                        TBool uptodate = CheckLocalCopyL( iDocumentList[index] );
+                        #ifdef _DEBUG
+                            iXcapProtocol.WriteToLog( _L8( "  Cache: %d" ), uptodate );
+                        #endif
+                        if( !uptodate )
+                            User::LeaveIfError( iUpdateList.Append( iDocumentList[index] ) );
+                        index++;
+                        }
+                    }
+                User::RequestComplete( iClientStatus, iStatus.Int() );
+                }
+                break;
+            case ERefreshDocuments:
+                {
+                CXdmDocumentNode* node = iUpdateList[iUpdateIndex];
+                #ifdef _DEBUG
+                    iXcapProtocol.WriteToLog( _L8( "  Index:    %d" ), iUpdateIndex );
+                    iXcapProtocol.WriteToLog( _L8( "  Document: %x" ), node );
+                    iXcapProtocol.WriteToLog( _L8( "  Error:    %d" ), iStatus.Int() );
+                #endif
+                TPtrC8 root = iXcapProtocol.Transport().RootUri();
+                TPtrC docName = ExtractDocumentUriL( root, node );
+                TXdmCompletionData* data = iHttpRetrieval->ResponseData();
+                TPtrC8 responseData( data->iResponseData->Des() );
+                TPtrC8 eTag( data->iETag->Des() );
+                RXcapCache* cache = iXcapProtocol.Cache();
+                cache->Store( eTag, docName, root, responseData  );
+                iHttpRetrieval->ReleaseResponseData();
+                UpdateNextDocumentL();
+                }
+                break;
+            default:
+                #ifdef _DEBUG
+                    iXcapProtocol.WriteToLog( _L8( "  Default case, unknown state %d - Status: %d" ),
+                                               iUpdatePhase, iStatus.Int() );
+                #endif
+                if( iClientStatus != NULL )
+                    User::RequestComplete( iClientStatus, KErrUnknown );  
+                break;
+            }   
+        }
+    else
+        {
+        #ifdef _DEBUG
+            iXcapProtocol.WriteToLog( _L8( "  Operation failed with %d" ), iStatus.Int() );
+        #endif
+        User::RequestComplete( iClientStatus, iStatus.Int() );
+        }
+    }
+
+// ---------------------------------------------------------
+// CXcapDirectory::CheckLocalCopyL
+// 
+// ---------------------------------------------------------
+//
+TBool CXcapDirectory::CheckLocalCopyL( const CXdmDocumentNode* aDocumentNode )
+    {
+    /*#ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDirectory::CheckLocalCopyL()" ) );
+    #endif*/
+    TBool ret = EFalse;
+    TPtrC8 root = iXcapProtocol.Transport().RootUri();
+    TPtrC docName = ExtractDocumentUriL( root, aDocumentNode );
+    TPtrC etag( aDocumentNode->Attribute( KDocumentETag )->AttributeValue() );
+    HBufC8* etag8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L( etag );
+    CleanupStack::PushL( etag8 );
+    RXcapCache* cache = iXcapProtocol.Cache();
+    ret = cache != NULL ? cache->IsCurrent( etag8->Des(), docName, root ) == KErrNone : ETrue;
+    CleanupStack::PopAndDestroy();  //etag8
+    return ret;
+    }
+
+// ---------------------------------------------------------
+// CXcapDirectory::ExtractDocumentUriL
+// 
+// ---------------------------------------------------------
+//
+TPtrC CXcapDirectory::ExtractDocumentUriL( const TDesC8& aRootUri,
+                                           const CXdmDocumentNode* aDocumentNode )
+    {
+    /*#ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDirectory::ExtractDocumentUri()" ) );
+    #endif*/
+    const TUint8 KHttpHostSeparator = 47;
+    _LIT8( KHttpDoubleHostSeparator,  "//" );
+    TPtrC uri( aDocumentNode->Attribute( KDocumentUri )->AttributeValue() );
+    if( uri[0] == KHttpHostSeparator ) //Relative URI
+        return uri;
+    else
+        {
+        TInt index = aRootUri.Find( KHttpDoubleHostSeparator );
+        TPtrC8 root( aRootUri.Right( aRootUri.Length() - index - 2 ) );
+        HBufC8* uri8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L( uri );
+        CleanupStack::PushL( uri8 );
+        TPtr8 desc( uri8->Des() );
+        index = desc.Find( root );
+        CleanupStack::PopAndDestroy();  //uri8
+        return index >= 0 ? uri.Right( uri.Length() - root.Length() - index ) : TPtrC();
+        }
+    }
+
+// ----------------------------------------------------
+// CXcapDirectory::DocumentCount
+// 
+// ----------------------------------------------------
+//
+TInt CXcapDirectory::DocumentCount()
+    {
+    return iDocumentCount;
+    }
+
+// ----------------------------------------------------
+// CXcapDirectory::DocumentType
+// 
+// ----------------------------------------------------
+//
+TXdmDocType CXcapDirectory::DocumentTypeL( TInt aIndex ) const
+    {
+    TXdmDocType type = EXdmDocGeneral;
+    if( iUpdatePhase <= EDirPhaseIdle )
+        User::Leave( KErrNotReady );
+    else if( iDocumentCount > 0 && ( aIndex >= 0 && aIndex < iDocumentCount ) )
+        type = FindAUID( *iDocumentList[aIndex] );
+    return type;
+    } 
+
+// ----------------------------------------------------
+// CXcapDirectory::FindAUID
+// 
+// ----------------------------------------------------
+//
+TXdmDocType CXcapDirectory::FindAUID( const CXdmDocumentNode& aEntryNode ) const
+    {
+    TXdmDocType documentType = EXdmDocGeneral;
+    HBufC8* buf = aEntryNode.Attribute( KDocumentUri )->EightBitValueLC();
+    if( buf )
+        {
+        TPtrC8 uri( buf->Des() );
+        if( uri.Find( KXdmCapabilityUsageAUID ) >= 0 )
+            documentType = EXdmCapabilities;
+        else if( uri.Find( KXdmPocUserAccessUsageAUID ) >= 0 )
+            documentType = EXdmPoCUserAccessPolicy;
+        else if( uri.Find( KXdmPocGroupUsageAUID ) >= 0 )
+            documentType = EXdmPoCGroup;
+        else if( uri.Find( KXdmResourceListsUsageAUID ) >= 0 )
+            documentType = EXdmResourceLists;
+        else if( uri.Find( KXdmOmaPresRulesUsageAUID ) >= 0 )
+            documentType = EXdmIetfPresenceRules;
+        else if( uri.Find( KXdmDirectoryUsageAUID ) >= 0 )
+            documentType = EXdmDirectory;
+        else if( uri.Find( KXdmSharedXDMUsageAUID ) >= 0 )
+            documentType = EXdmSharedXdm;
+        else if( uri.Find( KXdmRlsServicesUsageAUID ) >= 0 )
+            documentType = EXdmRlsServices;
+        CleanupStack::PopAndDestroy();  //EightBitValueLC()
+        }
+    return documentType;
+    }
+                 
+// ----------------------------------------------------
+// CXcapDirectory::Document
+// 
+// ----------------------------------------------------
+//
+TPtrC CXcapDirectory::Document( TInt aIndex ) const
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDirectory::Document() - Index: %d" ), aIndex );
+    #endif
+    TChar slash = 47;
+    if( aIndex >= 0 && aIndex < iDocumentList.Count() ) 
+        {
+        TPtrC ret;
+        TPtrC uri = iDocumentList[aIndex]->Attribute( KDocumentUri )->AttributeValue();
+        TInt index = uri.LocateReverse( slash );
+        index > 0 ? ret.Set( uri.Right( uri.Length() - index - 1 ) ) : ret.Set( uri );
+        return ret;
+        }
+    else return TPtrC();
+    }
+        
+// ----------------------------------------------------
+// CXcapDirectory::DirectoryPath
+// 
+// ----------------------------------------------------
+//
+TPtrC CXcapDirectory::DirectoryPath() const
+    {
+    return iAUID != NULL ? iAUID->Des() : TPtrC();
+    }
+
+// ----------------------------------------------------
+// CXcapDirectory::CancelUpdate
+// 
+// ----------------------------------------------------
+//
+void CXcapDirectory::CancelUpdate()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDirectory::CancelUpdate()" ) );
+    #endif
+    Cancel();
+    }
+    
+// ---------------------------------------------------------
+// CXcapDirectory::DoCancel
+// 
+// ---------------------------------------------------------
+//
+void CXcapDirectory::DoCancel()
+    {
+    #ifdef _DEBUG
+        iXcapProtocol.WriteToLog( _L8( "CXcapDirectory::DoCancel()" ) );
+    #endif
+    switch( iUpdatePhase )
+        {
+        case EDirPhaseIdle:
+            break;
+        case EUpdateDocumentList:
+            {
+            CXcapDocument* doc = ( CXcapDocument* )iDirectoryDoc;
+            doc->CancelUpdate();
+            }
+            break;
+        case ERefreshDocuments:
+            iHttpRetrieval->CancelRequest();
+            break;
+        default:
+            break;
+        }
+    User::RequestComplete( iClientStatus, KErrCancel );
+    }
+
+
+
+