00001
00002
00003
00004
00005
00006 #include "opluginloader.h"
00007 #include "oconfig.h"
00008 #include "odebug.h"
00009
00010 #include <qpe/qpeapplication.h>
00011
00012 #include <qdir.h>
00013 #include <qdict.h>
00014 #include <qtl.h>
00015 #include <qfile.h>
00016
00017 #include <stdlib.h>
00018
00019
00020
00021 namespace Opie {
00022 namespace Core {
00023 namespace Internal {
00024 struct OPluginLibraryHolder {
00025 static OPluginLibraryHolder *self();
00026 QLibrary *ref( const QString& );
00027 void deref( QLibrary* );
00028 private:
00029
00030 OPluginLibraryHolder();
00031 ~OPluginLibraryHolder();
00032 QDict<QLibrary> m_libs;
00033 static OPluginLibraryHolder* m_self;
00034 };
00035
00036 OPluginLibraryHolder* OPluginLibraryHolder::m_self = 0;
00037 OPluginLibraryHolder* OPluginLibraryHolder::self() {
00038 if ( !m_self )
00039 m_self = new OPluginLibraryHolder;
00040
00041 return m_self;
00042 }
00043
00044 OPluginLibraryHolder::OPluginLibraryHolder() {}
00045 OPluginLibraryHolder::~OPluginLibraryHolder() {}
00046
00047
00048
00049
00050
00051
00052
00053
00054 QLibrary* OPluginLibraryHolder::ref(const QString& str) {
00055 QLibrary *lib = m_libs[str];
00056
00057
00058 if ( !lib ) {
00059 lib = new QLibrary( str, QLibrary::Immediately );
00060 if ( !lib->isLoaded() ) {
00061 delete lib;
00062 return 0l;
00063 }
00064 }
00065
00066
00067 m_libs.insert( str, lib );
00068 return lib;
00069 }
00070
00071
00072
00073
00074 void OPluginLibraryHolder::deref( QLibrary* lib ) {
00075 if ( !lib )
00076 return;
00077
00078 QString str = lib->library();
00079
00080 (void) m_libs.take( str );
00081 if ( !m_libs[str] ) {
00082 lib->unload();
00083 delete lib;
00084 }
00085 }
00086 }
00087
00092 bool operator<( const OPluginItem& l, const OPluginItem& r ) {
00093 return l.position() > r.position();
00094 }
00095
00096 bool operator>( const OPluginItem& l, const OPluginItem& r ) {
00097 return l.position() < r.position();
00098 }
00099
00100 bool operator<=( const OPluginItem& l, const OPluginItem& r ) {
00101 return l.position() >= r.position();
00102 }
00103
00110 OPluginItem::OPluginItem()
00111 : m_pos( -1 ) {
00112 }
00113
00128 OPluginItem::OPluginItem( const QString& name, const QString& path, bool b, int pos )
00129 : m_name( name ), m_path( path ), m_enabled( b ), m_pos( pos )
00130 {}
00131
00135 OPluginItem::~OPluginItem() {
00136 }
00137
00146 bool OPluginItem::isEmpty()const {
00147 if ( m_pos != -1 ) return false;
00148 if ( m_enabled ) return false;
00149 if ( !m_name.isEmpty() ) return false;
00150 if ( !m_path.isEmpty() ) return false;
00151
00152 return true;
00153 }
00154
00159 bool OPluginItem::operator==( const OPluginItem& r )const{
00160 if ( m_pos != r.m_pos ) return false;
00161 if ( m_enabled != r.m_enabled) return false;
00162 if ( m_name != r.m_name ) return false;
00163 if ( m_path != r.m_path ) return false;
00164 return true;
00165 }
00166
00171 bool OPluginItem::operator!=( const OPluginItem& r )const{
00172 return !( *this == r );
00173 }
00174
00179 QString OPluginItem::name()const {
00180 return m_name;
00181 }
00182
00186 QString OPluginItem::path()const {
00187 return m_path;
00188 }
00189
00193 bool OPluginItem::isEnabled()const {
00194 return m_enabled;
00195 }
00196
00207 int OPluginItem::position()const{
00208 return m_pos;
00209 }
00210
00216 void OPluginItem::setName( const QString& name ) {
00217 m_name = name;
00218 }
00219
00225 void OPluginItem::setPath( const QString& name ) {
00226 m_path = name;
00227 }
00228
00237 void OPluginItem::setEnabled( bool enabled ) {
00238 m_enabled = enabled;
00239 }
00240
00248 void OPluginItem::setPosition( int pos ) {
00249 m_pos = pos;
00250 }
00251
00252
00253
00281 OGenericPluginLoader::OGenericPluginLoader( const QString& name, bool isSorted)
00282 : m_dir( name ), m_autoDelete( false ), m_isSafeMode( false ),
00283 m_isSorted( isSorted )
00284 {
00285 setPluginDir( QPEApplication::qpeDir() + "plugins/"+name );
00286 readConfig();
00287 }
00288
00289
00296 OGenericPluginLoader::~OGenericPluginLoader() {
00297 if ( m_autoDelete )
00298 clear();
00299 }
00300
00309 void OGenericPluginLoader::setAutoDelete( bool t ) {
00310 m_autoDelete = t;
00311 }
00312
00316 bool OGenericPluginLoader::autoDelete()const{
00317 return m_autoDelete;
00318 }
00319
00326 void OGenericPluginLoader::clear() {
00327 QPtrDictIterator<QLibrary> it( m_library );
00328 for ( ;it.current(); )
00329 unload( static_cast<QUnknownInterface*>( it.currentKey() ) );
00330 }
00331
00340 void OGenericPluginLoader::unload( QUnknownInterface* iface ) {
00341 if ( !iface )
00342 return;
00343
00344 iface->release();
00345 Internal::OPluginLibraryHolder::self()->deref( m_library.take( iface ) );
00346 }
00347
00354 QString OGenericPluginLoader::name()const {
00355 return m_dir;
00356 }
00357
00358
00367 bool OGenericPluginLoader::isInSafeMode()const {
00368 return m_isSafeMode;
00369 }
00370
00371
00379 OPluginItem::List OGenericPluginLoader::allAvailable( bool sorted )const {
00380 OPluginItem::List lst;
00381 for ( QStringList::ConstIterator it = m_plugDirs.begin(); it != m_plugDirs.end(); ++it )
00382 lst += plugins( *it, sorted, false );
00383
00384 if ( sorted )
00385 qHeapSort( lst );
00386 return lst;
00387 }
00388
00395 OPluginItem::List OGenericPluginLoader::filtered( bool sorted )const {
00396 OPluginItem::List lst;
00397 for ( QStringList::ConstIterator it = m_plugDirs.begin(); it != m_plugDirs.end(); ++it )
00398 lst += plugins( *it, sorted, true );
00399
00400 if ( sorted )
00401 qHeapSort( lst );
00402 return lst;
00403 }
00404
00405
00417 QUnknownInterface* OGenericPluginLoader::load( const OPluginItem& item, const QUuid& uuid) {
00418
00419
00420
00421 QString pa = item.path();
00422 if ( pa.isEmpty() )
00423 return 0l;
00424
00425
00426
00427
00428
00429 setSafeMode( pa, true );
00430 QLibrary *lib = Internal::OPluginLibraryHolder::self()->ref( pa );
00431 if ( !lib ) {
00432 setSafeMode();
00433 return 0l;
00434 }
00435
00439 QUnknownInterface* iface=0;
00440 if ( lib->queryInterface( uuid, &iface ) == QS_OK ) {
00441 installTranslators( item.name() );
00442 m_library.insert( iface, lib );
00443 }else
00444 iface = 0;
00445
00446 setSafeMode();
00447
00448 return iface;
00449 }
00450
00454 void OGenericPluginLoader::readConfig() {
00455
00456
00457
00458 OConfig conf( m_dir + "-odpplugins" );
00459 conf.setGroup( "General" );
00460 m_isSafeMode = conf.readBoolEntry( "SafeMode", false );
00461 }
00462
00466 void OGenericPluginLoader::setSafeMode(const QString& str, bool b) {
00467 OConfig conf( m_dir + "-odpplugins" );
00468 conf.setGroup( "General" );
00469 conf.writeEntry( "SafeMode", b );
00470 conf.writeEntry( "CrashedPlugin", str );
00471 }
00472
00479 void OGenericPluginLoader::setPluginDirs( const QStringList& lst ) {
00480 m_plugDirs = lst;
00481 }
00482
00488 void OGenericPluginLoader::setPluginDir( const QString& str) {
00489 m_plugDirs.clear();
00490 m_plugDirs.append( str );
00491 }
00492
00493
00497 bool OGenericPluginLoader::isSorted()const{
00498 return m_isSorted;
00499 }
00500
00501
00502
00503
00504
00505
00509 QString OGenericPluginLoader::unlibify( const QString& str ) {
00510 QString st = str.mid( str.find( "lib" )+3 );
00511 #ifdef Q_OS_MACX
00512 return st.left( st.findRev( ".dylib" ) );
00513 #else
00514 return st.left( st.findRev( ".so" ) );
00515 #endif
00516 }
00517
00530 OPluginItem::List OGenericPluginLoader::plugins( const QString& _dir, bool sorted, bool disabled )const {
00531 #ifdef Q_OS_MACX
00532 QDir dir( _dir, "lib*.dylib" );
00533 #else
00534 QDir dir( _dir, "lib*.so" );
00535 #endif
00536
00537
00538 OPluginItem::List lst;
00539
00540
00541
00542
00543
00544
00545
00546
00547 QMap<QString, int> positionMap;
00548 QMap<QString, int> excludedMap;
00549
00550
00551 OConfig cfg( m_dir+"-odpplugins" );
00552 cfg.setGroup( _dir );
00553
00554
00555 QStringList excludes = cfg.readListEntry( "Excluded", ',' );
00556 for ( QStringList::Iterator it = excludes.begin(); it != excludes.end(); ++it )
00557 excludedMap.insert( *it, -2 );
00558
00559 if ( sorted ) {
00560 QStringList pos = cfg.readListEntry( "Positions", '.' );
00561 QStringList::Iterator it = pos.begin();
00562 QString tmp; int i;
00563 while ( it != pos.end() ) {
00564 tmp = *it++; i = (*it++).toInt();
00565 positionMap.insert( tmp, i );
00566 }
00567
00568 }
00569
00570
00571
00572
00573 QStringList list = dir.entryList();
00574 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
00575 QString str = unlibify( *it );
00576 OPluginItem item( str, _dir + "/" + *it );
00577
00578 bool ex = excludedMap.contains( str );
00579
00580
00581
00582
00583
00584 if ( ex && !disabled)
00585 item.setEnabled( false );
00586 else if ( ex && disabled )
00587 continue;
00588 else if ( sorted )
00589 item.setPosition( positionMap[str] );
00590
00591
00592 lst.append( item );
00593 }
00594
00595 return lst;
00596 }
00597
00601 QStringList OGenericPluginLoader::languageList() {
00602 if ( m_languages.isEmpty() ) {
00603
00604
00605
00606
00607
00608
00609 QString str = ::getenv( "LANG" );
00610 m_languages += str;
00611 int pos = str.find( '@' );
00612 if( pos > 0 )
00613 m_languages += str.left( pos );
00614
00615
00616 pos = str.find( '.' );
00617 if ( pos > 0 )
00618 m_languages += str.left( pos );
00619
00620 int n_pos = str.find( '_' );
00621 if ( n_pos > 0 )
00622 m_languages += str.left( n_pos );
00623
00624 }
00625 return m_languages;
00626 }
00627
00632 void OGenericPluginLoader::installTranslators(const QString& type) {
00633 QStringList lst = languageList();
00634
00635
00636
00637
00638
00639 for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
00640 QTranslator* trans = new QTranslator( qApp );
00641 QString tfn = QPEApplication::qpeDir()+"i18n/" + *it + "/lib" + type + ".qm" ;
00642
00643
00644
00645
00646 if ( trans->load( tfn ) )
00647 qApp->installTranslator( trans );
00648 else
00649 delete trans;
00650 }
00651 }
00652
00665 OPluginLoader::OPluginLoader( const QString& name, bool sorted )
00666 : OGenericPluginLoader( name, sorted )
00667 {
00668 }
00669
00674 OPluginLoader::~OPluginLoader() {
00675 }
00676
00685 OPluginManager::OPluginManager( OGenericPluginLoader* loader)
00686 : m_loader( loader ), m_isSorted( false )
00687 {
00688 }
00689
00700 OPluginManager::OPluginManager( const QString& name, const OPluginItem::List& lst, bool isSorted)
00701 : m_loader( 0l ), m_cfgName( name ), m_plugins( lst ), m_isSorted( isSorted )
00702 {
00703 }
00704
00708 OPluginManager::~OPluginManager() {
00709 }
00710
00722 OPluginItem OPluginManager::crashedPlugin()const {
00723 return m_crashed;
00724 }
00725
00733 OPluginItem::List OPluginManager::managedPlugins()const {
00734 return m_plugins;
00735 }
00736
00748 void OPluginManager::setPosition( const OPluginItem& item) {
00749 replace( item );
00750 }
00751
00761 void OPluginManager::enable( const OPluginItem& item ) {
00762 setEnabled( item, true );
00763 }
00764
00773 void OPluginManager::disable( const OPluginItem& item) {
00774 setEnabled( item, false );
00775 }
00776
00788 void OPluginManager::setEnabled( const OPluginItem& _item, bool b ) {
00789 OPluginItem item = _item;
00790 item.setEnabled( b );
00791 replace( item );
00792 }
00793
00800 void OPluginManager::load() {
00801 OConfig cfg( configName() );
00802 cfg.setGroup( "General" );
00803 QString crashedPath = cfg.readEntry( "CrashedPlugin" );
00804
00805
00806 if ( m_loader )
00807 m_plugins = m_loader->allAvailable( m_loader->isSorted() );
00808
00809
00810 if ( crashedPath.isEmpty() )
00811 return;
00812
00813
00814 for ( OPluginItem::List::Iterator it = m_plugins.begin(); it != m_plugins.end(); ++it )
00815 if ( (*it).path() == crashedPath ) {
00816 m_crashed = *it;
00817 break;
00818 }
00819 }
00820
00821
00828 void OPluginManager::save() {
00829 QMap<QString, QStringList> excluded;
00830 QMap<QString, QStringList> positions;
00831 bool sorted = m_loader ? m_loader->isSorted() : m_isSorted;
00832
00833
00834
00835
00836 for ( OPluginItem::List::Iterator it = m_plugins.begin(); it != m_plugins.end(); ++it ) {
00837 OPluginItem item = *it;
00838 QString path = QFileInfo( item.path() ).dirPath(true);
00839 if ( sorted ) {
00840 positions[path].append( item.name() );
00841 positions[path].append( QString::number( item.position() ) );
00842 }
00843
00844 if ( !item.isEnabled() )
00845 excluded[path].append( item.name() );
00846 if ( !excluded.contains( path ) )
00847 excluded[path] = QString::null;
00848
00849 }
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 OConfig cfg( configName() );
00860
00861
00862 for ( QMap<QString, QStringList>::Iterator it = excluded.begin(); it != excluded.end(); ++it ) {
00863 OConfigGroupSaver saver( &cfg, it.key() );
00864 cfg.writeEntry("Excluded", it.data(), ',' );
00865 }
00866
00867
00868
00869
00870 for ( QMap<QString, QStringList>::Iterator it = positions.begin(); it != positions.end(); ++it ) {
00871 OConfigGroupSaver saver( &cfg, it.key() );
00872 cfg.writeEntry("Positions", it.data(), '.' );
00873 }
00874 }
00875
00879 QString OPluginManager::configName()const {
00880 QString str = m_loader ? m_loader->name() : m_cfgName;
00881 return str + "-odpplugins";
00882 }
00883
00887 void OPluginManager::replace( const OPluginItem& item ) {
00888 OPluginItem _item;
00889
00890
00891 for ( OPluginItem::List::Iterator it=m_plugins.begin();it != m_plugins.end(); ++it ) {
00892 _item = *it;
00893
00894 if ( _item.path() == item.path() &&
00895 _item.name() == item.name() ) {
00896 it = m_plugins.remove( it );
00897 m_plugins.append( item );
00898 return;
00899 }
00900
00901 }
00902 }
00903
00904 }
00905 }