qtecomplugins/xqplugins/src/xqpluginloaderprivate.cpp
branchRCL_3
changeset 10 cd2778e5acfe
parent 9 5d007b20cfd0
child 11 19a54be74e5e
equal deleted inserted replaced
9:5d007b20cfd0 10:cd2778e5acfe
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 *
       
     5 * This program is free software: you can redistribute it and/or modify
       
     6 * it under the terms of the GNU Lesser General Public License as published by
       
     7 * the Free Software Foundation, version 2.1 of the License.
       
     8 * 
       
     9 * This program is distributed in the hope that it will be useful,
       
    10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12 * GNU Lesser General Public License for more details.
       
    13 *
       
    14 * You should have received a copy of the GNU Lesser General Public License
       
    15 * along with this program.  If not, 
       
    16 * see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
       
    17 *
       
    18 * Description: This is the private implementation of the XQPluginLoader class.
       
    19 *
       
    20 */
       
    21 
       
    22 #include "xqpluginloaderprivate.h"
       
    23 #include "xqplugininfo.h"
       
    24 
       
    25 #include <qglobal.h>
       
    26 #include <QObject>
       
    27 #include <QLibrary>
       
    28 #include <QSettings>
       
    29 
       
    30 #include <xqplugin.h>
       
    31 
       
    32 #include "xqpluginfactory.h"
       
    33 
       
    34 #include <qstring.h>
       
    35 #include <qmutex.h>
       
    36 #include <qfileinfo.h>
       
    37 
       
    38 //TODO warning: use of internal include ??
       
    39 #include <qglobal.h>
       
    40 
       
    41 #include <ecom/ecom.h>
       
    42 #include <e32base.h>
       
    43 #include <e32std.h>
       
    44 #include <utf.h>
       
    45 
       
    46 #include "xqtecom.hrh"
       
    47 
       
    48 //TODO warning: use of Qt internal macro
       
    49 Q_GLOBAL_STATIC(QMutex, qt_pluginloader_mutex)
       
    50 
       
    51 typedef QMap<int, XQPluginLoaderPrivate*> PluginLoadersMap;
       
    52 //TODO warning: use of Qt internal macro
       
    53 Q_GLOBAL_STATIC(PluginLoadersMap, pluginLoadersMap)
       
    54 
       
    55 
       
    56 XQPluginLoaderPrivate::XQPluginLoaderPrivate( int requestedUid, const QString &version)
       
    57 :
       
    58 pHnd(0),
       
    59 fileName(),
       
    60 uid( requestedUid ),
       
    61 pluginInstance(0),
       
    62 loaderRefCount(1), 
       
    63 loaderUnloadCount(0)
       
    64 { 
       
    65     pluginLoadersMap()->insert(uid, this);
       
    66     Q_UNUSED(version);
       
    67 }
       
    68 
       
    69 XQPluginLoaderPrivate::~XQPluginLoaderPrivate()
       
    70 {
       
    71     PluginLoadersMap * const map = pluginLoadersMap();
       
    72     if (map) {
       
    73         XQPluginLoaderPrivate *that = map->take( uid );
       
    74         Q_ASSERT(this == that);
       
    75         Q_UNUSED(that);
       
    76     }
       
    77 }
       
    78 
       
    79 void XQPluginLoaderPrivate::release()
       
    80 {
       
    81     QMutexLocker locker(qt_pluginloader_mutex());
       
    82     if (!loaderRefCount.deref()) {
       
    83         delete this;
       
    84     }
       
    85 }
       
    86 
       
    87 XQPluginLoaderPrivate *XQPluginLoaderPrivate::findOrCreate(const QString &requestedFileName, const QString &version)
       
    88 {
       
    89     QString fileName(requestedFileName);
       
    90     if (fileName.endsWith(".qtplugin", Qt::CaseInsensitive)) {
       
    91         fileName.chop(8);
       
    92         fileName.append("dll");
       
    93     }
       
    94     
       
    95     XQPluginLoaderPrivate* retVal( NULL );
       
    96     TRAPD( err, findOrCreateL( retVal, fileName, version ) );
       
    97     if( KErrNone != err ) {
       
    98         retVal = findOrCreate( KNullUid.iUid, version );
       
    99         retVal->errorString = QString( "Unknown error %1" ).arg( err );
       
   100     }
       
   101     return retVal;
       
   102 }
       
   103 
       
   104 XQPluginLoaderPrivate *XQPluginLoaderPrivate::findOrCreate(int id, const QString &version)
       
   105 {
       
   106     QMutexLocker locker(qt_pluginloader_mutex());
       
   107     XQPluginLoaderPrivate *pluginLoader = pluginLoadersMap()->value( id );
       
   108     if ( pluginLoader ) {
       
   109         pluginLoader->loaderRefCount.ref();
       
   110     } else {
       
   111         pluginLoader = new XQPluginLoaderPrivate(id, version);
       
   112     }
       
   113     return pluginLoader;
       
   114 }
       
   115 
       
   116 void XQPluginLoaderPrivate::findOrCreateL( XQPluginLoaderPrivate*& pluginLoader, const QString &requestedFileName , const QString &version )
       
   117 {
       
   118     if( 0 >= requestedFileName.length() ) {
       
   119         User::Leave( KErrBadName );
       
   120     }
       
   121     TPtrC symbianFileName( requestedFileName.utf16(), requestedFileName.length() ); //set string content into descriptor
       
   122     TEComResolverParams resolverParams;
       
   123     RImplInfoPtrArray infoArr;
       
   124     TUid customResolverUid( KNullUid ), pluginInterfaceUid( KNullUid );
       
   125     customResolverUid.iUid = KEComDisplayNameResolverImplementationUid;
       
   126     pluginInterfaceUid.iUid  = KQtEcomPluginInterfaceUID;
       
   127     
       
   128     HBufC8* symbianFileNamePtr( CnvUtfConverter::ConvertFromUnicodeToUtf8L( symbianFileName ) );//convert file name to UTF8
       
   129     CleanupStack::PushL( symbianFileNamePtr );
       
   130     resolverParams.SetDataType( *symbianFileNamePtr );//initialize resolver params struct
       
   131     REComSession::ListImplementationsL( pluginInterfaceUid, resolverParams, customResolverUid, infoArr );//list matching plugins using custom resolver
       
   132     CleanupStack::PopAndDestroy( symbianFileNamePtr );
       
   133     
       
   134     if( 0 >= infoArr.Count() ) {
       
   135         User::Leave( KErrNotFound );
       
   136     }
       
   137     //analyse available plugins versions
       
   138     int optimalPluginOffset( 0 );
       
   139     for( int i( 0 ); i < infoArr.Count(); ++i ) {
       
   140         if( infoArr[ optimalPluginOffset ]->Version() < infoArr[ i ]->Version() ) {
       
   141             optimalPluginOffset = i;
       
   142         }
       
   143     }
       
   144     const int resolvedUid( infoArr[ optimalPluginOffset ]->ImplementationUid().iUid );
       
   145     infoArr.ResetAndDestroy();
       
   146     
       
   147     pluginLoader = findOrCreate( resolvedUid, version );
       
   148     User::LeaveIfNull( pluginLoader ); 
       
   149     pluginLoader->setFileName( requestedFileName );
       
   150 }
       
   151 
       
   152 bool XQPluginLoaderPrivate::isPlugin(QSettings *settings)
       
   153 {
       
   154     Q_UNUSED(settings)
       
   155     return true;
       
   156 }
       
   157 
       
   158 bool XQPluginLoaderPrivate::loadPlugin()
       
   159 {
       
   160     loaderUnloadCount.ref();
       
   161     if (pluginInstance) {
       
   162         return true;
       
   163     }
       
   164     pHnd = 0;
       
   165     errorString = "Can't load plugin.";
       
   166     if( KNullUid.iUid != uid ) {
       
   167         TRAPD(loadError, loadL());
       
   168         if( KErrNone == loadError ) {
       
   169             pHnd = 1;
       
   170             errorString.clear();
       
   171         }
       
   172     }
       
   173     return pHnd; 
       
   174 }
       
   175 
       
   176 void XQPluginLoaderPrivate::loadL()
       
   177 {
       
   178     CPluginFactory* pluginFactory = CPluginFactory::NewL( uid );
       
   179     pluginInstance = pluginFactory->createQtPlugin();
       
   180 }
       
   181 
       
   182 QObject* XQPluginLoaderPrivate::instance()
       
   183 {
       
   184     return pluginInstance;
       
   185 }
       
   186 
       
   187 bool XQPluginLoaderPrivate::unload()
       
   188 {
       
   189     if (!pHnd)
       
   190         return false;
       
   191     
       
   192     if (!loaderUnloadCount.deref()) { // only unload if ALL loader instances wanted to
       
   193         if (pluginInstance)
       
   194             delete pluginInstance;
       
   195             pHnd = 0;
       
   196     }
       
   197     
       
   198     return (pHnd == 0);
       
   199 }
       
   200 
       
   201 void XQPluginLoaderPrivate::setFileName( const QString& value )
       
   202 {
       
   203     fileName = value;
       
   204 }
       
   205 
       
   206 void XQPluginLoaderPrivate::listImplementationsL( 
       
   207         RImplInfoPtrArray& infoArr, 
       
   208         const QString &interfaceName, 
       
   209         QList<XQPluginInfo> &impls)
       
   210 {
       
   211     const TUid uid = { 0x20022FCE };
       
   212     TEComResolverParams resolverParams;
       
   213 
       
   214     HBufC8* ifName = HBufC8::NewLC(interfaceName.length());
       
   215     ifName->Des().Copy(TPtrC(interfaceName.utf16()));
       
   216     resolverParams.SetDataType(*ifName);
       
   217     REComSession::ListImplementationsL(uid, resolverParams, infoArr);
       
   218     CleanupStack::PopAndDestroy( ifName );
       
   219     for (int i( 0 ); i < infoArr.Count(); ++i) {
       
   220         const TDesC &name = infoArr[i]->DisplayName();
       
   221         QString dllName = QString::fromUtf16( 
       
   222                 reinterpret_cast<const ushort*>(name.Ptr()), 
       
   223                     name.Length());
       
   224         
       
   225         const TDesC8 &opaque_data = infoArr[i]->OpaqueData();
       
   226         QString opaqueData = QString::fromAscii( 
       
   227                         reinterpret_cast<const char*>( opaque_data.Ptr() ), 
       
   228                             opaque_data.Length());
       
   229         
       
   230         impls.append(XQPluginInfo(infoArr[i]->ImplementationUid().iUid, 
       
   231                                  infoArr[i]->Version(),
       
   232                                  dllName, 
       
   233                                  opaqueData));
       
   234     }
       
   235 }