mtpfws/mtpfw/dataproviders/proxydp/src/cmtpsetobjectproplist.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 27 Apr 2010 17:30:23 +0300
branchRCL_3
changeset 6 ef55b168cedb
parent 0 d0791faffa3f
permissions -rw-r--r--
Revision: 201004 Kit: 201017

// Copyright (c) 2006-2009 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 <mtp/cmtpobjectmetadata.h>
#include <mtp/cmtptypeobjectinfo.h>
#include <mtp/cmtptypeobjectproplist.h>
#include <mtp/mmtpdataproviderframework.h>
#include <mtp/mtpprotocolconstants.h>
#include <mtp/tmtptyperequest.h>

#include "cmtpdataprovider.h"
#include "cmtpdataprovidercontroller.h"
#include "cmtpobjectmgr.h"
#include "cmtpparserrouter.h"
#include "cmtpsetobjectproplist.h"
#include "mtpproxydppanic.h"
#include "rmtpframework.h"
#include "cmtpstoragemgr.h"

/**
Two-phase construction method
@param aFramework    The data provider framework
@param aConnection    The connection from which the request comes
@return a pointer to the created request processor object
*/ 
MMTPRequestProcessor* CMTPSetObjectPropList::NewL(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection)
    {
    CMTPSetObjectPropList* self = new (ELeave) CMTPSetObjectPropList(aFramework, aConnection);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }

/**
Destructor
*/    
CMTPSetObjectPropList::~CMTPSetObjectPropList()
    {
    delete iObjectPropList;
    iDpList.Close();
    iSingletons.Close();
    }

/**
Standard c++ constructor
*/    
CMTPSetObjectPropList::CMTPSetObjectPropList(MMTPDataProviderFramework& aFramework, MMTPConnection& aConnection) :
    CMTPRequestProcessor(aFramework, aConnection, 0, NULL)
    {
    
    }
    
/**
Second phase constructor.
*/
void CMTPSetObjectPropList::ConstructL()
    {
    iSingletons.OpenL();
    }

/**
SetObjectPropList request handler
*/    
void CMTPSetObjectPropList::ServiceL()
    {
    delete iObjectPropList;
    iObjectPropList = NULL;
    iObjectPropList = CMTPTypeObjectPropList::NewL();
    ReceiveDataL(*iObjectPropList);    
    }

/**
Override to handle the response phase of SetObjectPropList requests
@return EFalse
*/
TBool CMTPSetObjectPropList::DoHandleResponsePhaseL()
    {
    iDpIdx = 0;
    iPropertyIdx = 0;
    iDpListCreated = EFalse;
    iPropertyIdx = 0;
    iDpList.Reset();
    iObjectPropList->ResetCursor();             
    Reschedule(KErrNone);
    return EFalse;
    }

#ifdef _DEBUG
void CMTPSetObjectPropList::ProxyReceiveDataL(MMTPType& aData, const TMTPTypeRequest& aRequest, MMTPConnection& aConnection, TRequestStatus& aStatus)
#else
void CMTPSetObjectPropList::ProxyReceiveDataL(MMTPType& aData, const TMTPTypeRequest& /*aRequest*/, MMTPConnection& /*aConnection*/, TRequestStatus& aStatus)
#endif
    {
    __ASSERT_DEBUG(iRequest == &aRequest && &iConnection == &aConnection, Panic(EMTPNotSameRequestProxy));
    __ASSERT_DEBUG(aData.Type() == EMTPTypeObjectPropListDataset, Panic(EMTPInvalidDataType));
    

	CMTPTypeObjectPropList* targetObjectPropList = static_cast<CMTPTypeObjectPropList*>(&aData); 
	targetObjectPropList->AppendObjectPropListL(*iObjectPropList);

    TRequestStatus* status = &aStatus;
    User::RequestComplete(status, KErrNone);
    }
    
void CMTPSetObjectPropList::ProxySendDataL(const MMTPType& /*aData*/, const TMTPTypeRequest& /*aRequest*/, MMTPConnection& /*aConnection*/, TRequestStatus& /*aStatus*/)
    {
    Panic(EMTPWrongRequestPhase);
    }
    
#ifdef _DEBUG    
void CMTPSetObjectPropList::ProxySendResponseL(const TMTPTypeResponse& aResponse, const TMTPTypeRequest& aRequest, MMTPConnection& aConnection, TRequestStatus& aStatus)
#else
void CMTPSetObjectPropList::ProxySendResponseL(const TMTPTypeResponse& aResponse, const TMTPTypeRequest& /*aRequest*/, MMTPConnection& /*aConnection*/, TRequestStatus& aStatus)
#endif
    {
    __ASSERT_DEBUG(iRequest == &aRequest && &iConnection == &aConnection, Panic(EMTPNotSameRequestProxy));
    iResponseCode = static_cast<TMTPResponseCode>(aResponse.Uint16(TMTPTypeResponse::EResponseCode));
    iPropertyIdx = aResponse.Uint32(TMTPTypeResponse::EResponseParameter1);
    TRequestStatus* status = &aStatus;
    User::RequestComplete(status, KErrNone);
    }

#ifdef _DEBUG    
void CMTPSetObjectPropList::ProxyTransactionCompleteL(const TMTPTypeRequest& aRequest, MMTPConnection& aConnection)
#else
void CMTPSetObjectPropList::ProxyTransactionCompleteL(const TMTPTypeRequest& /*aRequest*/, MMTPConnection& /*aConnection*/)
#endif
    {
    __ASSERT_DEBUG(iRequest == &aRequest && &iConnection == &aConnection, Panic(EMTPNotSameRequestProxy));
    const TInt KErr(iResponseCode == EMTPRespCodeOK ? KErrNone : KErrGeneral);    
    if (KErr == KErrNone)
        {
        ++iDpIdx;
        }
    Reschedule(KErr);
    }

void CMTPSetObjectPropList::RunL()
    {    
    if (iStatus == KErrNone) // send request to the next dp
        {
        if (!iDpListCreated)
            {    
            // Data provider list under construction.
            iResponseCode = EMTPRespCodeOK;
            const TUint KElementCount(iObjectPropList->NumberOfElements());
            const TUint KRunLength(32);
		
            for (TUint i(0); ((i < KRunLength) && (iPropertyIdx < KElementCount) && (iResponseCode == EMTPRespCodeOK)); ++i)
                {
				iPropertyIdx++;
				CMTPTypeObjectPropListElement& element=iObjectPropList->GetNextElementL();			
                const TUint32 KHandle(element.Uint32L(CMTPTypeObjectPropListElement::EObjectHandle));
                const TUint16 KPropCode(element.Uint16L(CMTPTypeObjectPropListElement::EPropertyCode));
                CMTPParserRouter::TRoutingParameters params(*iRequest, iConnection);
                params.SetParam(CMTPParserRouter::TRoutingParameters::EParamObjectHandle, KHandle);
                params.SetParam(CMTPParserRouter::TRoutingParameters::EParamObjectPropCode, KPropCode);
                                
                CMTPObjectMetaData* meta(CMTPObjectMetaData::NewLC());
                if (!iSingletons.ObjectMgr().ObjectL(KHandle, *meta))
                    {
                    // Invalid object handle.
                    iResponseCode = EMTPRespCodeInvalidObjectHandle;
                    }
                else if(!iSingletons.StorageMgr().IsReadWriteStorage(meta->Uint(CMTPObjectMetaData::EStorageId)))
                	{
					iResponseCode = EMTPRespCodeAccessDenied;
                	}
                else
                    {
                    RArray<TUint> targets;
                    CleanupClosePushL(targets);
                    iSingletons.Router().RouteOperationRequestL(params, targets);
                    __ASSERT_DEBUG((targets.Count() <= 1), User::Invariant());
                    if (targets.Count() == 1)
                        {
                        iDpList.InsertInOrder(targets[0]);
                        }
                    else
                        {
                        // Unsupported object propertycode.
                        iResponseCode = EMTPRespCodeObjectPropNotSupported;
                        }
                    CleanupStack::PopAndDestroy(&targets);
                    }
                CleanupStack::PopAndDestroy(meta);
                
                if (iResponseCode != EMTPRespCodeOK)
                    {
                    // If an error occurs at this point then no properties have been updated.
                    iPropertyIdx = 0;
                    iDpList.Reset();
                    }
                }	                
            if ((iPropertyIdx < KElementCount) && (iResponseCode == EMTPRespCodeOK))
                {
                Reschedule(KErrNone);
                }
            else
                {
                iDpListCreated = ETrue;
                }
            }
            
        if (iDpListCreated)
            {
            if (iDpIdx < iDpList.Count())
                {
                iSingletons.DpController().DataProviderL(iDpList[iDpIdx]).ExecuteProxyRequestL(Request(), Connection(), *this);
                }
            else
                {
                SendResponseL(iResponseCode, 1, &iPropertyIdx);                
                }
            }
        }
    else
        {
        if (!iDpListCreated)
            {
            /* 
            If an error occurs prior to starting the proxy transaction cycles 
            then no properties have been updated.
            */
            iPropertyIdx = 0;
            }
            
        if (iResponseCode == EMTPRespCodeOK)
            {
            iResponseCode = EMTPRespCodeGeneralError;
            }
        SendResponseL(iResponseCode, 1, &iPropertyIdx);
        }    
    }

/**
Reschedules the active object with the specified completion code.
@param aError The asynchronous request completion code.
*/
void CMTPSetObjectPropList::Reschedule(TInt aError)
    {
    SetActive();
    TRequestStatus* status = &iStatus;
    User::RequestComplete(status, aError);
    }