diff -r 885c2596c964 -r 5d007b20cfd0 qtecomplugins/xqplugins/src/xqpluginloaderprivate.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qtecomplugins/xqplugins/src/xqpluginloaderprivate.cpp Tue Aug 31 16:02:37 2010 +0300 @@ -0,0 +1,235 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, version 2.1 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this program. If not, +* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/". +* +* Description: This is the private implementation of the XQPluginLoader class. +* +*/ + +#include "xqpluginloaderprivate.h" +#include "xqplugininfo.h" + +#include +#include +#include +#include + +#include + +#include "xqpluginfactory.h" + +#include +#include +#include + +//TODO warning: use of internal include ?? +#include + +#include +#include +#include +#include + +#include "xqtecom.hrh" + +//TODO warning: use of Qt internal macro +Q_GLOBAL_STATIC(QMutex, qt_pluginloader_mutex) + +typedef QMap PluginLoadersMap; +//TODO warning: use of Qt internal macro +Q_GLOBAL_STATIC(PluginLoadersMap, pluginLoadersMap) + + +XQPluginLoaderPrivate::XQPluginLoaderPrivate( int requestedUid, const QString &version) +: +pHnd(0), +fileName(), +uid( requestedUid ), +pluginInstance(0), +loaderRefCount(1), +loaderUnloadCount(0) +{ + pluginLoadersMap()->insert(uid, this); + Q_UNUSED(version); +} + +XQPluginLoaderPrivate::~XQPluginLoaderPrivate() +{ + PluginLoadersMap * const map = pluginLoadersMap(); + if (map) { + XQPluginLoaderPrivate *that = map->take( uid ); + Q_ASSERT(this == that); + Q_UNUSED(that); + } +} + +void XQPluginLoaderPrivate::release() +{ + QMutexLocker locker(qt_pluginloader_mutex()); + if (!loaderRefCount.deref()) { + delete this; + } +} + +XQPluginLoaderPrivate *XQPluginLoaderPrivate::findOrCreate(const QString &requestedFileName, const QString &version) +{ + QString fileName(requestedFileName); + if (fileName.endsWith(".qtplugin", Qt::CaseInsensitive)) { + fileName.chop(8); + fileName.append("dll"); + } + + XQPluginLoaderPrivate* retVal( NULL ); + TRAPD( err, findOrCreateL( retVal, fileName, version ) ); + if( KErrNone != err ) { + retVal = findOrCreate( KNullUid.iUid, version ); + retVal->errorString = QString( "Unknown error %1" ).arg( err ); + } + return retVal; +} + +XQPluginLoaderPrivate *XQPluginLoaderPrivate::findOrCreate(int id, const QString &version) +{ + QMutexLocker locker(qt_pluginloader_mutex()); + XQPluginLoaderPrivate *pluginLoader = pluginLoadersMap()->value( id ); + if ( pluginLoader ) { + pluginLoader->loaderRefCount.ref(); + } else { + pluginLoader = new XQPluginLoaderPrivate(id, version); + } + return pluginLoader; +} + +void XQPluginLoaderPrivate::findOrCreateL( XQPluginLoaderPrivate*& pluginLoader, const QString &requestedFileName , const QString &version ) +{ + if( 0 >= requestedFileName.length() ) { + User::Leave( KErrBadName ); + } + TPtrC symbianFileName( requestedFileName.utf16(), requestedFileName.length() ); //set string content into descriptor + TEComResolverParams resolverParams; + RImplInfoPtrArray infoArr; + TUid customResolverUid( KNullUid ), pluginInterfaceUid( KNullUid ); + customResolverUid.iUid = KEComDisplayNameResolverImplementationUid; + pluginInterfaceUid.iUid = KQtEcomPluginInterfaceUID; + + HBufC8* symbianFileNamePtr( CnvUtfConverter::ConvertFromUnicodeToUtf8L( symbianFileName ) );//convert file name to UTF8 + CleanupStack::PushL( symbianFileNamePtr ); + resolverParams.SetDataType( *symbianFileNamePtr );//initialize resolver params struct + REComSession::ListImplementationsL( pluginInterfaceUid, resolverParams, customResolverUid, infoArr );//list matching plugins using custom resolver + CleanupStack::PopAndDestroy( symbianFileNamePtr ); + + if( 0 >= infoArr.Count() ) { + User::Leave( KErrNotFound ); + } + //analyse available plugins versions + int optimalPluginOffset( 0 ); + for( int i( 0 ); i < infoArr.Count(); ++i ) { + if( infoArr[ optimalPluginOffset ]->Version() < infoArr[ i ]->Version() ) { + optimalPluginOffset = i; + } + } + const int resolvedUid( infoArr[ optimalPluginOffset ]->ImplementationUid().iUid ); + infoArr.ResetAndDestroy(); + + pluginLoader = findOrCreate( resolvedUid, version ); + User::LeaveIfNull( pluginLoader ); + pluginLoader->setFileName( requestedFileName ); +} + +bool XQPluginLoaderPrivate::isPlugin(QSettings *settings) +{ + Q_UNUSED(settings) + return true; +} + +bool XQPluginLoaderPrivate::loadPlugin() +{ + loaderUnloadCount.ref(); + if (pluginInstance) { + return true; + } + pHnd = 0; + errorString = "Can't load plugin."; + if( KNullUid.iUid != uid ) { + TRAPD(loadError, loadL()); + if( KErrNone == loadError ) { + pHnd = 1; + errorString.clear(); + } + } + return pHnd; +} + +void XQPluginLoaderPrivate::loadL() +{ + CPluginFactory* pluginFactory = CPluginFactory::NewL( uid ); + pluginInstance = pluginFactory->createQtPlugin(); +} + +QObject* XQPluginLoaderPrivate::instance() +{ + return pluginInstance; +} + +bool XQPluginLoaderPrivate::unload() +{ + if (!pHnd) + return false; + + if (!loaderUnloadCount.deref()) { // only unload if ALL loader instances wanted to + if (pluginInstance) + delete pluginInstance; + pHnd = 0; + } + + return (pHnd == 0); +} + +void XQPluginLoaderPrivate::setFileName( const QString& value ) +{ + fileName = value; +} + +void XQPluginLoaderPrivate::listImplementationsL( + RImplInfoPtrArray& infoArr, + const QString &interfaceName, + QList &impls) +{ + const TUid uid = { 0x20022FCE }; + TEComResolverParams resolverParams; + + HBufC8* ifName = HBufC8::NewLC(interfaceName.length()); + ifName->Des().Copy(TPtrC(interfaceName.utf16())); + resolverParams.SetDataType(*ifName); + REComSession::ListImplementationsL(uid, resolverParams, infoArr); + CleanupStack::PopAndDestroy( ifName ); + for (int i( 0 ); i < infoArr.Count(); ++i) { + const TDesC &name = infoArr[i]->DisplayName(); + QString dllName = QString::fromUtf16( + reinterpret_cast(name.Ptr()), + name.Length()); + + const TDesC8 &opaque_data = infoArr[i]->OpaqueData(); + QString opaqueData = QString::fromAscii( + reinterpret_cast( opaque_data.Ptr() ), + opaque_data.Length()); + + impls.append(XQPluginInfo(infoArr[i]->ImplementationUid().iUid, + infoArr[i]->Version(), + dllName, + opaqueData)); + } +}