diff -r d27dfa8884ad -r da2cedce4920 piprofiler/engine/src/WriterPluginLoader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piprofiler/engine/src/WriterPluginLoader.cpp Tue May 25 14:22:58 2010 +0300 @@ -0,0 +1,565 @@ +/* +* Copyright (c) 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 FILES +#include "WriterPluginLoader.h" +//#include +#include // CnvUtfConverter +#include + +// constants + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::NewL +// +// EPOC two-phased constructor +// ---------------------------------------------------------------------------- +// +CWriterPluginLoader* CWriterPluginLoader::NewL() + { + CWriterPluginLoader* self = new( ELeave ) CWriterPluginLoader; + CleanupStack::PushL( self ); + self->ConstructL( ); + CleanupStack::Pop( self ); + return self; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::CWriterPluginLoader +// +// C++ default constructor can NOT contain any code, that +// might leave. +// ---------------------------------------------------------------------------- +// +CWriterPluginLoader::CWriterPluginLoader() : CActive( EPriorityStandard ) + { + LOGTEXT(_L("CWriterPluginLoader()::CWriterPluginLoader()" )); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::ConstructL +// +// EPOC default constructor can leave. +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::ConstructL( ) + { + LOGTEXT(_L("CWriterPluginLoader()::ConstructL()" )); + + // get list of implementations + CWriterPluginInterface::ListAllImplementationsL( iImplInfoArray ); + + CActiveScheduler::Add( this ); + } + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::~CWriterPluginLoader +// +// Destructor +// ---------------------------------------------------------------------------- +// +CWriterPluginLoader::~CWriterPluginLoader() + { + LOGTEXT(_L("CWriterPluginLoader()::~CWriterPluginLoader()") ); + + AbortAsyncLoad(); + + Cancel(); + + // reset ECOM implementation info array + iImplInfoArray.ResetAndDestroy(); // This is needed + iImplInfoArray.Close(); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::LoadAsync +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::LoadAsyncL( CArrayPtrFlat* aPluginArray ) + { + iPluginArray = aPluginArray; + + // Reset iterator: + iImplInfoArrayIterator = 0; + + LOGSTRING2( "CWriterPluginLoader()::Implementation info count: %d", + iImplInfoArray.Count() ); + + NotifyProgress(); + + //Begin CActive asynchronous loop. + CompleteOwnRequest(); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::LoadSyncL +// +// +// ---------------------------------------------------------------------------- +// +CWriterPluginInterface& CWriterPluginLoader::LoadSyncL( TUid aImplementationUid ) + { + Cancel(); + CWriterPluginInterface* plugin = NULL; + + // Get a list of all implementations, even though we only want one specific + // one. There appears to be no way to otherwise extract a specific implementation + // info object :( + // Search for the implementation that matches aImplementationUid + const TInt impCount = iImplInfoArray.Count(); + for( TInt i=0; iImplementationUid() == aImplementationUid ) + { + TRAPD(ret, plugin = &CreatePluginInstanceL( *info ); ); + if( ret == KErrNone ) + { + // Plugin ownership is transfered to iPluginArray + InsertPluginInOrderL( plugin, iPluginArray ); + } + else + { + // Error note is displayed even if plugin is not loaded + LOGSTRING2("CWriterPluginLoader::LoadSyncL() - plugin load failed, error %d", ret); + } + break; + } + } + + if ( plugin == NULL ) + { + User::Leave( KErrNotFound ); + } + return *plugin; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::AbortAsyncLoad +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::AbortAsyncLoad() + { + LOGTEXT(_L("CWriterPluginLoader()::AbortAsyncLoad()" )); + Cancel(); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::RunL +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::RunL() + { + iRunLDebugCount++; + LoadNextPluginL(); + + // Check if there are still more plugins to be loaded: + if ( iImplInfoArrayIterator < iImplInfoArray.Count() ) + { + NotifyProgress(); + // Continue CActive asynchronous loop. + CompleteOwnRequest(); + } + else + { + // All plugins loaded: + LOGTEXT(_L("CWriterPluginLoader()::Loading plugins finished." )); + NotifyFinished(); + } + } + + +// --------------------------------------------------------------------------- +// CScGenreItemConstructionConductor::CompleteOwnRequest +// +// Issue request complete notification. +// --------------------------------------------------------------------------- +void CWriterPluginLoader::CompleteOwnRequest() + { + TRequestStatus* status = &iStatus; + User::RequestComplete( status, KErrNone ); + SetActive(); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::RunError +// +// +// ---------------------------------------------------------------------------- +// +TInt CWriterPluginLoader::RunError( TInt aError ) + { + // This method is called when a plugin loading fails. + // Always "fake" the return value so that ActiveSchedule + // keeps running and later plugins are continued to be loaded. + // Check if still plugins to be loaded: + if( iImplInfoArrayIterator < iImplInfoArray.Count() ) + { + NotifyProgress(); + + //Continue CActive asynchronous loop. + CompleteOwnRequest(); + } + else // All plugins loaded: + { + NotifyFinished(); + } + + if ( aError == KLeaveExit ) + { + return KLeaveExit; + } + + return KErrNone; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::DoCancel +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::DoCancel() + { + + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::NotifyProgress +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::NotifyProgress() + { + if( iObserver ) + { + iObserver->HandlePluginLoaded( MWriterPluginLoadObserver::EWriterSuccess); + } + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::NotifyFinished +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::NotifyFinished() + { + if( iObserver ) + { + iObserver->HandlePluginLoaded( MWriterPluginLoadObserver::EWriterFinished ); + } + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::SetObserver +// +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::SetObserver(MWriterPluginLoadObserver* aObserver) + { + LOGSTRING2("CWriterPluginLoader()::Observer set:0x%X", aObserver); + iObserver = aObserver; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::ParseToUid +// Parses a UID from descriptor of form '0xNNNNNNNN' where N is hexadecimal. +// +// ---------------------------------------------------------------------------- +// +TInt CWriterPluginLoader::ParseToUid( const TDesC8& aSource, TUid& aTarget ) + { + // Remove "0x" from the descriptor if it exists + _LIT8(KHexPrefix, "0x"); + + TPtrC8 pSource( aSource ); + const TInt prefixPosition = pSource.Find( KHexPrefix ); + if ( prefixPosition != KErrNotFound ) + { + pSource.Set( aSource.Mid( prefixPosition + KHexPrefix().Length() ) ); + } + + // Parse to integer + TLex8 lex( pSource ); + TUint integer = 0; + + // Parse using TRadix::EHex as radix: + const TInt err = lex.Val( integer, EHex ); + aTarget.iUid = integer; + + if( err != KErrNone ) + { + // If parsing parent UID failed, do not load plugin: + LOGSTRING2( + "CWriterPluginLoader()::Parsing parent UID failed. Error code:%d", + err ); + } + return err; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::ParseOrderNumber +// +// +// ---------------------------------------------------------------------------- +// +TInt CWriterPluginLoader::ParseOrderNumber( const TDesC8& aSource, TInt& aOrderNumber ) + { + // Parse plugin's order number from opaque_data: + TLex8 lex( aSource ); + const TInt orderErr = lex.Val( aOrderNumber ); + return orderErr; + } + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::LoadNextPluginL +// Iterate through iImplInfoArray. Load the plugin if it is eligible for +// loading. Loaded plugin is added to iPluginArray. Each time a plugin is +// loaded, iObserver is notified. +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::LoadNextPluginL() + { + // Iterate through iImplInfoArray. This loop continues between function + // calls. Therefore member variable iImplInfoArrayIterator is used as a + // counter. Loop will break when match is found and continues on next RunL. + for( ; iImplInfoArrayIterator < iImplInfoArray.Count(); ) + { + const CImplementationInformation* info = + iImplInfoArray[ iImplInfoArrayIterator ]; + + iImplInfoArrayIterator++; + + // If this plugin is OK -> load it: + LOGSTRING2( "CWriterPluginLoader() %S eligible for parent", + &info->DisplayName() ); + CWriterPluginInterface* plugin = NULL; + TInt error(KErrNone); + // Create plugin. Trap leave for debugging purposes. + TRAP( error, plugin = &CreatePluginInstanceL( *info ); ); + if( error == KErrNone ) + { + // Plugin ownership is transfered to iPluginArray + InsertPluginInOrderL( plugin, iPluginArray ); + } + else + { + LOGSTRING2("CWriterPluginLoader::LoadNextPluginL() - plugin load failed, error %d", error); + } + // Wait for next round + break; + } + } + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::CreatePluginInstanceL +// +// +// ---------------------------------------------------------------------------- +// + +CWriterPluginInterface& CWriterPluginLoader::CreatePluginInstanceL( + const CImplementationInformation& aImpInfo ) + { + // Now we can load the plugin + const TUid implUid = aImpInfo.ImplementationUid(); + + CWriterPluginInterface* plugin = CWriterPluginInterface::NewL( implUid , (TAny*)&aImpInfo.DisplayName() ); + CleanupStack::PushL ( plugin ); + + TInt orderNumber(0); + const TInt orderErr = ParseOrderNumber( aImpInfo.OpaqueData(), orderNumber ); + + if ( orderErr == KErrNone && orderNumber >= 0 ) + { + plugin->iOrder = orderNumber; + } + + CleanupStack::Pop( plugin ); // CWriterController is now responsible for this memory. + + return *plugin; + } + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::SortPluginsL +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::SortPluginsL( + CArrayPtrFlat* aPlugins ) + { + RPointerArray plugins; + TLinearOrder order( CWriterPluginLoader::Compare ); + + // Insertion will also order + for( TInt i = 0; i < aPlugins->Count(); i++ ) + { + plugins.InsertInOrderL( (*aPlugins)[i], order ); + } + + // Replace original array content with sorted items + aPlugins->Reset(); + for( TInt i = 0; i < plugins.Count(); i++ ) + { + aPlugins->AppendL( plugins[i] ); + } + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::Compare +// +// Compare two plugins. +// Precedence: +// [1. plugin provider category] +// 2. plugin order number +// 3. plugin caption +// Plugin provider gategory is currently disabled (not supported yet). +// ---------------------------------------------------------------------------- +// +TInt CWriterPluginLoader::Compare( const CWriterPluginInterface& aFirst, + const CWriterPluginInterface& aSecond ) + { + return CompareIndex( aFirst, aSecond ); + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::InsertPluginInOrderL +// +// ---------------------------------------------------------------------------- +// +void CWriterPluginLoader::InsertPluginInOrderL( + CWriterPluginInterface* aPlugin, + CArrayPtrFlat* aPlugins ) + { + CWriterPluginInterface* comparedPlugin; + TInt comparison = 0; + TBool inserted = EFalse; + + for( TInt i = 0; i < aPlugins->Count(); i++ ) + { + comparedPlugin = (*aPlugins)[i]; + // Optimization: do not call time consuming Compare() multiple times! + comparison = Compare( *aPlugin, *comparedPlugin ); + if( comparison < 0 ) + { + aPlugins->InsertL( i, aPlugin ); + inserted = ETrue; + break; + } + else if( comparison == 0 ) + { + aPlugins->InsertL( i+1, aPlugin ); + inserted = ETrue; + break; + } + } + // Plugin was not before any other plugin - make sure it's appended + if( !inserted ) + { + aPlugins->AppendL( aPlugin ); + } + + #ifdef _GS_PLUGINLOADER_SORTING_TRACES + PrintOrderTraces( aPlugins ); + #endif // _GS_PLUGINLOADER_SORTING_TRACES + + } + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::CompareIndex +// +// +// ---------------------------------------------------------------------------- +// + +TInt CWriterPluginLoader::CompareIndex( const CWriterPluginInterface& aFirst, + const CWriterPluginInterface& aSecond ) + { + TInt comparison = KWriterComparisonEqual; + // The plugin having index is before the one not having one + + if( aFirst.iOrder == KWriterPluginNotIndexed && + aSecond.iOrder == KWriterPluginNotIndexed ) + { + // Neither have index -> equal + comparison = KWriterComparisonEqual; + } + else if( aFirst.iOrder == KWriterPluginNotIndexed ) + { + // The plugin having index is before the one not having one + comparison = KWriterComparisonAfter; + } + else if( aSecond.iOrder == KWriterPluginNotIndexed ) + { + // The plugin having index is before the one not having one + comparison = KWriterComparisonBefore; + } + else if( aFirst.iOrder < aSecond.iOrder ) + { + // Compare actual index values + comparison = KWriterComparisonBefore; + } + else if( aFirst.iOrder > aSecond.iOrder ) + { + // Compare actual index values + comparison = KWriterComparisonAfter; + } + return comparison; + } + + +// ---------------------------------------------------------------------------- +// CWriterPluginLoader::GetDocument +// +// +// ---------------------------------------------------------------------------- +// +/* +CWriterBaseDocument* CWriterPluginLoader::GetDocument() + { + CWriterBaseDocument* document = static_cast( iAppUi->Document() ); + return document; + } +*/ + +// End of File