diff -r 000000000000 -r 4e1aa6a622a0 mediator/src/Server/MediatorServerEventHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mediator/src/Server/MediatorServerEventHandler.cpp Tue Feb 02 00:53:00 2010 +0200 @@ -0,0 +1,549 @@ +/* +* 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: Event handling logic for the Mediator Server +* +*/ + + +// INCLUDE FILES +#include + +#include "MediatorServerEventHandler.h" +#include "MediatorServerObjects.h" +#include "MediatorServiceDefs.h" +#include "Debug.h" + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CMediatorServerEventHandler::CMediatorServerEventHandler +// ----------------------------------------------------------------------------- +// +CMediatorServerEventHandler::CMediatorServerEventHandler( + CMediatorServerObjectHandler& aObjectHandler ) + : CActive( EPriorityStandard ), iObjectHandler( aObjectHandler ) + { + } + +// ----------------------------------------------------------------------------- +// CMediatorServerEventHandler::ConstructL +// ----------------------------------------------------------------------------- +// +void CMediatorServerEventHandler::ConstructL() + { + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CMediatorServerEventHandler::NewL +// ----------------------------------------------------------------------------- +// +CMediatorServerEventHandler* CMediatorServerEventHandler::NewL( + CMediatorServerObjectHandler& aObjectHandler ) + { + LOG(_L("[Mediator Server]\t CMediatorServerEventHandler::NewL")); + CMediatorServerEventHandler* self + = new( ELeave ) CMediatorServerEventHandler( aObjectHandler ); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + +// ----------------------------------------------------------------------------- +// CMediatorServerEventHandler::~CMediatorServerEventHandler +// ----------------------------------------------------------------------------- +// +CMediatorServerEventHandler::~CMediatorServerEventHandler() + { + Cancel(); + // Clear event list + iEventServiceList.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CMediatorServerEventHandler::DoCancel +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerEventHandler::DoCancel() + { + TRACE(Print(_L("[Mediator Server]\t CMediatorServerEventHandler::DoCancel\n"))); + } + +// ----------------------------------------------------------------------------- +// CMediatorServerEventHandler::RunL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerEventHandler::RunL() + { + TRACE(Print(_L("[Mediator Server]\t CMediatorServerEventHandler::RunL status %d\n"), iStatus.Int() )); + + // Should be no errors unless cancel + if ( iStatus == KErrNone ) + { + if ( iEventServiceList.Count() > 0 ) + { + CEvent* serviceEvent = iEventServiceList[0]; // Take the first + iEventServiceList.Remove(0); // remove event from array + if ( serviceEvent ) + { + // Get event information + TUid domain = serviceEvent->Domain(); + TUid category = serviceEvent->Category(); + TInt eventId = serviceEvent->Id(); + const TDesC8& data = serviceEvent->ParameterData(); + + RPointerArray& observers + = serviceEvent->GetObservers(); + + // Loop through the observer array and send notifications + for ( TInt index = 0; index < observers.Count(); index++ ) + { + MMediatorServerEventObserver* observer = observers[index]; + if ( observer ) + { + TRAP_IGNORE( observer->MediatorEventL( domain, + category, + eventId, + data ) ); + } + } + delete serviceEvent; + } + // Continue if there's still more to serve + if ( iEventServiceList.Count() > 0 ) + { + SetActive(); + iStatus = KRequestPending; + TRequestStatus* stat = &iStatus; + User::RequestComplete( stat, KErrNone ); + } + } + } + LOG(_L("[Mediator Server]\t CMediatorServerEventHandler::RunL end")); + } + +// ----------------------------------------------------------------------------- +// CMediatorServerEventHandler::RegisterEventListL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerEventHandler::RegisterEventListL( + TMediatorCategory aCategory, + const REventList& aEvents, + TSecureId aSecureId ) + { + LOG(_L("[Mediator Server]\t CMediatorServerEventHandler::RegisterEventListL")); + // Check that domain exists --> if not add new + CDomain* domain = iObjectHandler.FindDomain( aCategory.iDomain ); + if ( !domain ) + { + domain = iObjectHandler.AddDomainL( aCategory.iDomain ); + } + + // Check that category exists --> if not add new + TInt ignore = 0; // not used here + CCategory* category = domain->FindCategory( aCategory.iCategory, ignore ); + if ( !category ) + { + category = domain->AddCategoryL( aCategory.iCategory ); + } + + // Loop through the events and add them to list + // Take the possible error to variable + TInt error = KErrNone; + TBool stop = EFalse; + TInt index = 0; + for ( index = 0; index < aEvents.Count() && !stop; index++ ) + { + CEvent* newEvent = CEvent::NewL( aEvents[index] ); + CleanupStack::PushL( newEvent ); + newEvent->SetSecureId( aSecureId ); + newEvent->SetCommitState( CItem::EAdded ); + TInt addError = category->AddEvent( newEvent ); + if ( addError ) + { + ERROR_TRACE(Print(_L("[Mediator] CMediatorServerEventHandler::RegisterEventListL: addError=%d\n"), addError ) ); + ERROR_TRACE(Print(_L("[Mediator] Failed to add event %d to category %d of domain %d\n"), newEvent->Id(), + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + // in case of error, delete event and take error + CleanupStack::PopAndDestroy( newEvent ); + error = addError; + stop = ETrue; + } + else + { + // Event has been added properly --> just pop + CleanupStack::Pop( newEvent ); + } + } + + TRACE(Print(_L("[Mediator Server]\t Events registered:\n"))); + TRACE(Print(_L("[Mediator Server]\t Success/count: %d/%d \tstatus: %d"), index, aEvents.Count(), error )); + // Check error if we need to do partial recovery + if ( error != KErrNone ) + { + // Remove events that already have been added + category->RollbackEvents(); + } + else + { + // Complete event list update + category->CommitEvents(); + + // Use the object handler to notify events + iObjectHandler.EventsAdded( aCategory.iDomain, + aCategory.iCategory, + aEvents ); + } + // In the end leave if error --> client gets error code + User::LeaveIfError( error ); + } + +// ----------------------------------------------------------------------------- +// CMediatorServerEventHandler::UnregisterEventListL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerEventHandler::UnregisterEventListL( TMediatorCategory aCategory, + const REventList& aEvents, + TSecureId aSecureId ) + { + CCategory* category = iObjectHandler.CategoryL( aCategory ); + TInt error = KErrNone; + if ( category ) + { + + TBool stop = EFalse; + TInt index = 0; + // Loop through the list of events and unregister those. + for ( index = 0; index < aEvents.Count() && !stop; index++ ) + { + TInt eventIndex = 0; + TEvent removeEvent = aEvents[index]; + CEvent* eventPtr = category->FindEvent( removeEvent.iEventId, eventIndex ); + if ( !eventPtr ) + { + ERROR_LOG(_L("[Mediator] CMediatorServerEventHandler::UnregisterEventListL: Event not found\n") ); + ERROR_TRACE(Print(_L("[Mediator] Failed to remove event %d in category %d of domain %d\n"), removeEvent.iEventId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + error = KErrMediatorEventNotFound; + stop = ETrue; + } + else + { + // Found the event --> is it own registration + if ( eventPtr->SecureId() != aSecureId ) + { + ERROR_LOG(_L("[Mediator] CMediatorServerEventHandler::UnregisterEventListL: Secure ID mismatch\n") ); + ERROR_TRACE(Print(_L("[Mediator] eventPtr->SecureId()=0x%x, aSecureId=0x%x\n"), eventPtr->SecureId().iId, + aSecureId.iId ) ); + error = KErrMediatorSecureIdMismatch; + stop = ETrue; + } + else // Should be ok to unregister + { + eventPtr->SetCommitState( CItem::ERemoved ); + } + } + } + + TRACE(Print(_L("[Mediator Server]\t Events unregistered:\n"))); + TRACE(Print(_L("[Mediator Server]\t Success/count: %d/%d \tstatus: %d"), index, aEvents.Count(), error )); + + // Check error status --> if there's error, need to roll back + if ( error != KErrNone ) + { + // Cancel event removal + category->RollbackEvents(); + } + else + { + // Complete event removal + category->CommitEvents(); + // Use the object handler to notify event removal + iObjectHandler.EventsRemoved( aCategory.iDomain, + aCategory.iCategory, + aEvents ); + } + } + // Leave in case of error situation + User::LeaveIfError( error ); + } + +// ----------------------------------------------------------------------------- +// CMediatorServerEventHandler::SubscribeEventListL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerEventHandler::SubscribeEventListL( + TMediatorCategory aCategory, + const REventList& aEvents, + TCapabilitySet aCaps, + MMediatorServerEventObserver* aObserver ) + { + LOG(_L("[Mediator Server]\t CMediatorServerEventHandler::SubscribeEventListL")); + TInt error = KErrNone; + TBool stop = EFalse; + TInt index = 0; + // Find domain & category + CCategory* category = iObjectHandler.CategoryL( aCategory ); + if ( category ) + { + // Loop through the list of subscribed events + for ( index = 0; index < aEvents.Count() && !stop; index++ ) + { + TEvent newEvent = aEvents[index]; + TInt ignore = 0; // Not used + CEvent* eventPtr = category->FindEvent( newEvent.iEventId, ignore ); + if ( !eventPtr ) + { + error = KErrMediatorEventNotFound; + stop = ETrue; // Partial failure --> stop processing + } + else + { + // Check capabilities + // Capabilities are checked so that boolean ETrue is returned + // when all parameter caps can be found from aCaps + if ( !aCaps.HasCapabilities( eventPtr->Policy() ) ) + { +#ifdef _DEBUG + for ( TInt index = 0; index < ECapability_Limit; index++ ) + { + TCapabilitySet eventCaps = eventPtr->Policy(); + TBool event = eventCaps.HasCapability( (TCapability) index ); + TBool requestor = aCaps.HasCapability( (TCapability) index ); + if ( event && !requestor ) + { + ERROR_TRACE(Print(_L("[Mediator] CMediatorServerEventHandler::SubscribeEventListL: capability %d missing \n"), index )); + ERROR_TRACE(Print(_L("[Mediator] Failed to subscribe event %d in category %d of domain %d\n"), newEvent.iEventId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + } + } +#endif // _DEBUG + error = KErrPermissionDenied; + stop = ETrue; + } + // Check (major) version match + if ( newEvent.iVersion.iMajor != eventPtr->Version().iMajor ) + { + ERROR_LOG(_L("[Mediator] CMediatorServerEventHandler::SubscribeEventListL: Version mismatch\n")); + ERROR_TRACE(Print(_L("[Mediator] Registered=%d, subscribed=%d \n"), eventPtr->Version().iMajor, + newEvent.iVersion.iMajor ) ); + ERROR_TRACE(Print(_L("[Mediator] Failed to subscribe event %d in category %d of domain %d\n"), newEvent.iEventId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + // There's a major version mismatch + error = KErrMediatorVersionMismatch; + stop = ETrue; + } + if ( !error ) // Everything ok? + { + // Everything is ok, register subscriber + TInt status = eventPtr->AddObserver( aObserver ); + // If there's double subscription, ignore error + // otherwise return the error + if ( status && status != KErrMediatorAlreadySubscribed ) + { + ERROR_TRACE(Print(_L("[Mediator] CMediatorServerEventHandler::SubscribeEventListL: error=%d\n"), status) ); + ERROR_TRACE(Print(_L("[Mediator] Failed to subscribe event %d in category %d of domain %d\n"), newEvent.iEventId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + error = status; + stop = ETrue; + } + TRACE(Print(_L("[Mediator Server]\t subscription status: %d\n"), status)); + } + } + } + + TRACE(Print(_L("[Mediator Server]\t Events subscribed:\n"))); + TRACE(Print(_L("[Mediator Server]\t Processed/Total: %d/%d \tstatus: %d"), index, aEvents.Count(), error )); + // Check error status --> if there's error, need to roll back + if ( error != KErrNone ) + { + // Loop the subscribed events and unsubscribe those + // Index - 1 is because index points to failed item --> stop before processing it again + for ( TInt newIndex = 0; newIndex < index - 1; newIndex++ ) + { + TEvent event = aEvents[newIndex]; + TInt ignore = 0; // Not used + CEvent* eventPtr = category->FindEvent( event.iEventId, ignore ); + if ( eventPtr ) + { + // Nothing can be done in case of error --> ignore return value + TInt ignore = eventPtr->RemoveObserver( aObserver ); + } + } + } + } + // In the end leave if we have error + User::LeaveIfError( error ); + + } + +// ----------------------------------------------------------------------------- +// CMediatorServerEventHandler::UnsubscribeEventListL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerEventHandler::UnsubscribeEventListL( + TMediatorCategory aCategory, + const REventList& aEvents, + MMediatorServerEventObserver* aObserver ) + { + LOG(_L("[Mediator Server]\t CMediatorServerEventHandler::UnsubscribeEventListL")); + // Find correct category + CCategory* category = iObjectHandler.CategoryL( aCategory ); + TInt error = KErrNone; + TInt index = 0; + + if ( category ) + { + TBool stop = EFalse; + // Loop through the list of events to be unsubscribed + for ( index = 0; index < aEvents.Count() && !stop; index++ ) + { + TEvent event = aEvents[index]; + TInt ignore = 0; // Not used + CEvent* eventPtr = category->FindEvent( event.iEventId, ignore ); + if ( !eventPtr ) + { + ERROR_LOG(_L("[Mediator] CMediatorServerEventHandler::UnsubscribeEventListL: event not found\n")); + ERROR_TRACE(Print(_L("[Mediator] Failed to unsubscribe event %d in category %d of domain %d\n"), event.iEventId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + + error = KErrMediatorEventNotFound; + stop = ETrue; // Partial failure --> stop processing + } + else + { + // Everything is ok, unsubscribe + TInt status = eventPtr->RemoveObserver( aObserver ); + // If there's no subscription existing, ignore error + // otherwise return the error + if ( status != KErrMediatorNoSubscription ) + { + ERROR_TRACE(Print(_L("[Mediator] CMediatorServerEventHandler::UnsubscribeEventListL: status=%d\n"), status ) ); + ERROR_TRACE(Print(_L("[Mediator] Failed to unsubscribe event %d in category %d of domain %d\n"), event.iEventId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + error = status; + stop = ETrue; + } + TRACE(Print(_L("[Mediator Server]\t unsubscribe status: %d\n"), status)); + } + } + + TRACE(Print(_L("[Mediator Server]\t Events unsubscribed:\n"))); + TRACE(Print(_L("[Mediator Server]\t Success/count: %d/%d \tstatus: %d"), index, aEvents.Count(), error )); + + // Check error status --> if there's error, need to roll back + if ( error != KErrNone ) + { + // Loop the unsubscribed events and subscribe those + for ( TInt newIndex = 0; newIndex < index; newIndex++ ) + { + TEvent event = aEvents[newIndex]; + TInt ignore = 0; // Not used + CEvent* eventPtr = category->FindEvent( event.iEventId, ignore ); + if ( eventPtr ) + { + // Nothing can be done in case of error --> ignore return value + TInt ignore = eventPtr->AddObserver( aObserver ); + } + } + } + } + // In the end leave if we have error + User::LeaveIfError( error ); + } + +// ----------------------------------------------------------------------------- +// CMediatorServerEventHandler::RaiseEventL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CMediatorServerEventHandler::RaiseEventL( TMediatorCategory aCategory, + MediatorService::TEvent aEvent, + const TDesC8& aData ) + { + LOG(_L("[Mediator Server]\t CMediatorServerEventHandler::RaiseEventL")); + // Find correct category + CCategory* category = iObjectHandler.CategoryL( aCategory ); + if ( category ) + { + TInt ignore = 0; // Not used + CEvent* eventPtr = category->FindEvent( aEvent.iEventId, ignore ); + + // Check that event was found + if ( !eventPtr ) + { + ERROR_LOG(_L("[Mediator] CMediatorServerEventHandler::RaiseEventL: event not found\n")); + ERROR_TRACE(Print(_L("[Mediator] Failed to raise event %d in category %d of domain %d\n"), aEvent.iEventId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + User::Leave( KErrMediatorEventNotFound ); + } + + // Check the version information match (major + if ( eventPtr->Version().iMajor != aEvent.iVersion.iMajor ) + { + ERROR_LOG(_L("[Mediator] CMediatorServerEventHandler::RaiseEventL: Version mismatch\n")); + ERROR_TRACE(Print(_L("[Mediator] Registered=%d, subscribed=%d \n"), eventPtr->Version().iMajor, + aEvent.iVersion.iMajor ) ); + ERROR_TRACE(Print(_L("[Mediator] Failed to raise event %d in category %d of domain %d\n"), aEvent.iEventId, + aCategory.iCategory.iUid, + aCategory.iDomain.iUid ) ); + User::Leave( KErrMediatorVersionMismatch ); + } + + + RPointerArray& observers + = eventPtr->GetObservers(); + + // Loop through the observer array and send notifications + for ( TInt index = 0; index < observers.Count(); index++ ) + { + MMediatorServerEventObserver* observer = observers[index]; + if ( observer ) + { + + TRAP_IGNORE( observer->MediatorEventL( aCategory.iDomain, + aCategory.iCategory, + aEvent.iEventId, + aData ) ); + } + } + } + } + +// End of File