374 changes: 145 additions & 229 deletions src/core/qgsproviderregistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include <QDir>
#include <QLibrary>


#include "qgis.h"
#include "qgsdataprovider.h"
#include "qgslogger.h"
Expand Down Expand Up @@ -65,13 +64,14 @@ QgsProviderRegistry::QgsProviderRegistry( QString pluginPath )
// check all libs in the current plugin directory and get name and descriptions
//TODO figure out how to register and identify data source plugin for a specific
//TODO layer type
/* char **argv = qApp->argv();
QString appDir = argv[0];
int bin = appDir.findRev("/bin", -1, false);
QString baseDir = appDir.left(bin);
QString mLibraryDirectory = baseDir + "/lib"; */
#if 0
char **argv = qApp->argv();
QString appDir = argv[0];
int bin = appDir.findRev( "/bin", -1, false );
QString baseDir = appDir.left( bin );
QString mLibraryDirectory = baseDir + "/lib";
#endif
mLibraryDirectory = pluginPath;

mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );

Expand All @@ -94,134 +94,96 @@ QgsProviderRegistry::QgsProviderRegistry( QString pluginPath )
output->setTitle( QObject::tr( "No Data Providers" ) );
output->setMessage( msg, QgsMessageOutput::MessageText );
output->showMessage();
return;
}
else

QListIterator<QFileInfo> it( mLibraryDirectory.entryInfoList() );
while ( it.hasNext() )
{
const QFileInfoList list = mLibraryDirectory.entryInfoList();
QListIterator<QFileInfo> it( list );
QFileInfo fi;
QFileInfo fi( it.next() );

while ( it.hasNext() )
QLibrary myLib( fi.filePath() );
if ( !myLib.load() )
{
fi = it.next();

QLibrary *myLib = new QLibrary( fi.filePath() );

bool loaded = myLib->load();
//we will build up a debug message and print on one line to avoid terminal spam
QString myMessage = "Checking " + myLib->fileName() + " : " ;

if ( loaded )
{
// get the description and the key for the provider plugin
isprovider_t *isProvider = ( isprovider_t * ) cast_to_fptr( myLib->resolve( "isProvider" ) );

//MH: Added a further test to detect non-provider plugins linked to provider plugins.
//Only pure provider plugins have 'type' not defined
isprovider_t *hasType = ( isprovider_t * ) cast_to_fptr( myLib->resolve( "type" ) );

if ( !hasType && isProvider )
{
// check to see if this is a provider plugin
if ( isProvider() )
{
// looks like a provider. get the key and description
description_t *pDesc = ( description_t * ) cast_to_fptr( myLib->resolve( "description" ) );
providerkey_t *pKey = ( providerkey_t * ) cast_to_fptr( myLib->resolve( "providerKey" ) );
if ( pDesc && pKey )
{
// add this provider to the provider map
mProviders[pKey()] =
new QgsProviderMetadata( pKey(), pDesc(), myLib->fileName() );
//myMessage += "Loaded " + QString(pDesc()) + " ok";

// now get vector file filters, if any
fileVectorFilters_t *pFileVectorFilters =
( fileVectorFilters_t * ) cast_to_fptr( myLib->resolve( "fileVectorFilters" ) );
//load database drivers
databaseDrivers_t *pDatabaseDrivers =
( databaseDrivers_t * ) cast_to_fptr( myLib->resolve( "databaseDrivers" ) );
if ( pDatabaseDrivers )
{
mDatabaseDrivers = pDatabaseDrivers();
}
//load directory drivers
directoryDrivers_t *pDirectoryDrivers =
( directoryDrivers_t * ) cast_to_fptr( myLib->resolve( "directoryDrivers" ) );
if ( pDirectoryDrivers )
{
mDirectoryDrivers = pDirectoryDrivers();
}
//load protocol drivers
protocolDrivers_t *pProtocolDrivers =
( protocolDrivers_t * ) cast_to_fptr( myLib->resolve( "protocolDrivers" ) );
if ( pProtocolDrivers )
{
mProtocolDrivers = pProtocolDrivers();
}

if ( pFileVectorFilters )
{
QString vectorFileFilters = pFileVectorFilters();

// now get vector file filters, if any
fileVectorFilters_t *pVectorFileFilters =
( fileVectorFilters_t * ) cast_to_fptr( myLib->resolve( "fileVectorFilters" ) );

if ( pVectorFileFilters )
{
QString fileVectorFilters = pVectorFileFilters();

if ( ! fileVectorFilters.isEmpty() )
{
mVectorFileFilters += fileVectorFilters;
myMessage += QString( "... loaded ok (and with %1 file filters)" ).
arg( fileVectorFilters.split( ";;" ).count() );
}
else
{
//myMessage += ", but it has no vector file filters for " + QString(pKey());
myMessage += "... loaded ok (0 file filters)";
}
}
}
else
{
//myMessage += ", but unable to invoke fileVectorFilters()";
myMessage += "... loaded ok (null file filters)";
}
}
else
{
//myMessage += ", but unable to find one of the required provider functions (providerKey() or description()) in ";
myMessage += "...not usable";

}
}
else
{
//myMessage += ", but this is not a valid provider, skipping.";
myMessage += "..invalid";
}
}
else
{
//myMessage += ", but this is not a valid provider or has no type, skipping.";
myMessage += "..invalid (no type)";
}
}
else
{
myMessage += "...invalid (lib not loadable): ";
myMessage += myLib->errorString();
}

QgsDebugMsg( myMessage );

delete myLib;
QgsDebugMsg( QString( "Checking %1: ...invalid (lib not loadable): %2" ).arg( myLib.fileName() ).arg( myLib.errorString() ) );
continue;
}
}

//MH: Added a further test to detect non-provider plugins linked to provider plugins.
//Only pure provider plugins have 'type' not defined
isprovider_t *hasType = ( isprovider_t * ) cast_to_fptr( myLib.resolve( "type" ) );
if ( hasType )
{
QgsDebugMsg( QString( "Checking %1: ...invalid (has type method)" ).arg( myLib.fileName() ) );
continue;
}

// get the description and the key for the provider plugin
isprovider_t *isProvider = ( isprovider_t * ) cast_to_fptr( myLib.resolve( "isProvider" ) );
if ( !isProvider )
{
QgsDebugMsg( QString( "Checking %1: ...invalid (no isProvider method)" ).arg( myLib.fileName() ) );
continue;
}

// check to see if this is a provider plugin
if ( !isProvider() )
{
QgsDebugMsg( QString( "Checking %1: ...invalid (not a provider)" ).arg( myLib.fileName() ) );
continue;
}

// looks like a provider. get the key and description
description_t *pDesc = ( description_t * ) cast_to_fptr( myLib.resolve( "description" ) );
if ( !pDesc )
{
QgsDebugMsg( QString( "Checking %1: ...invalid (no description method)" ).arg( myLib.fileName() ) );
continue;
}

providerkey_t *pKey = ( providerkey_t * ) cast_to_fptr( myLib.resolve( "providerKey" ) );
if ( !pKey )
{
QgsDebugMsg( QString( "Checking %1: ...invalid (no providerKey method)" ).arg( myLib.fileName() ) );
continue;
}

// add this provider to the provider map
mProviders[pKey()] = new QgsProviderMetadata( pKey(), pDesc(), myLib.fileName() );

// load database drivers
databaseDrivers_t *pDatabaseDrivers = ( databaseDrivers_t * ) cast_to_fptr( myLib.resolve( "databaseDrivers" ) );
if ( pDatabaseDrivers )
{
mDatabaseDrivers = pDatabaseDrivers();
}

// load directory drivers
directoryDrivers_t *pDirectoryDrivers = ( directoryDrivers_t * ) cast_to_fptr( myLib.resolve( "directoryDrivers" ) );
if ( pDirectoryDrivers )
{
mDirectoryDrivers = pDirectoryDrivers();
}

// load protocol drivers
protocolDrivers_t *pProtocolDrivers = ( protocolDrivers_t * ) cast_to_fptr( myLib.resolve( "protocolDrivers" ) );
if ( pProtocolDrivers )
{
mProtocolDrivers = pProtocolDrivers();
}

// now get vector file filters, if any
fileVectorFilters_t *pFileVectorFilters = ( fileVectorFilters_t * ) cast_to_fptr( myLib.resolve( "fileVectorFilters" ) );
if ( pFileVectorFilters )
{
QString fileVectorFilters = pFileVectorFilters();

if ( !fileVectorFilters.isEmpty() )
mVectorFileFilters += fileVectorFilters;

QgsDebugMsg( QString( "Checking %1: ...loaded ok (%2 file filters)" ).arg( myLib.fileName() ).arg( fileVectorFilters.split( ";;" ).count() ) );
}
}
} // QgsProviderRegistry ctor


Expand Down Expand Up @@ -270,39 +232,33 @@ QString QgsProviderRegistry::library( QString const & providerKey ) const
QString QgsProviderRegistry::pluginList( bool asHTML ) const
{
Providers::const_iterator it = mProviders.begin();
QString list;

if ( mProviders.empty() )
{
list = QObject::tr( "No data provider plugins are available. No vector layers can be loaded" );
}
else
return QObject::tr( "No data provider plugins are available. No vector layers can be loaded" );

QString list;

if ( asHTML )
list += "<ol>";

while ( it != mProviders.end() )
{
if ( asHTML )
{
list += "<ol>";
}
while ( it != mProviders.end() )
{
QgsProviderMetadata *mp = ( *it ).second;

if ( asHTML )
{
list += "<li>" + mp->description() + "<br>";
}
else
{
list += mp->description() + "\n";
}

it++;
}
list += "<li>";

list += it->second->description();

if ( asHTML )
{
list += "</ol>";
}
list + "<br></li>";
else
list += "\n";

it++;
}

if ( asHTML )
list += "</ol>";

return list;
}

Expand Down Expand Up @@ -357,64 +313,33 @@ QgsDataProvider *QgsProviderRegistry::provider( QString const & providerKey, QSt
}

#endif

// load the data provider
QLibrary* myLib = new QLibrary( lib );

QgsDebugMsg( "Library name is " + myLib->fileName() );

bool loaded = myLib->load();
QLibrary myLib( lib );

if ( loaded )
QgsDebugMsg( "Library name is " + myLib.fileName() );
if ( !myLib.load() )
{
QgsDebugMsg( "Loaded data provider library" );
QgsDebugMsg( "Attempting to resolve the classFactory function" );

classFactoryFunction_t * classFactory =
( classFactoryFunction_t * ) cast_to_fptr( myLib->resolve( "classFactory" ) );

if ( classFactory )
{
QgsDebugMsg( "Getting pointer to a dataProvider object from the library" );

//XXX - This was a dynamic cast but that kills the Windows
// version big-time with an abnormal termination error
// QgsDataProvider* dataProvider = (QgsDataProvider*)
// (classFactory((const char*)(dataSource.utf8())));

QgsDataProvider * dataProvider = ( *classFactory )( &dataSource );

if ( dataProvider )
{
QgsDebugMsg( "Instantiated the data provider plugin" );
QgsDebugMsg( "provider name: " + dataProvider->name() );

delete myLib;
return dataProvider;
}
else
{
QgsMessageLog::logMessage( QObject::tr( "Unable to instantiate the data provider plugin %1" ).arg( lib ) );

delete dataProvider;

myLib->unload();
delete myLib;
return 0;
}
}
QgsMessageLog::logMessage( QObject::tr( "Failed to load %1: %2" ).arg( lib ).arg( myLib.errorString() ) );
return 0;
}
else

classFactoryFunction_t *classFactory = ( classFactoryFunction_t * ) cast_to_fptr( myLib.resolve( "classFactory" ) );
if ( !classFactory )
{
QgsMessageLog::logMessage( QObject::tr( "Failed to load %1: %2" ).arg( lib ).arg( myLib->errorString() ) );
delete myLib;
QgsDebugMsg( QString( "Failed to load %1: no classFactory method" ).arg( lib ) );
return 0;
}

QgsDebugMsg( "exiting" );

return 0; // factory didn't exist
QgsDataProvider *dataProvider = classFactory( &dataSource );
if ( !dataProvider )
{
QgsMessageLog::logMessage( QObject::tr( "Unable to instantiate the data provider plugin %1" ).arg( lib ) );
myLib.unload();
return 0;
}

QgsDebugMsg( QString( "Instantiated the data provider plugin: %1" ).arg( dataProvider->name() ) );
return dataProvider;
} // QgsProviderRegistry::setDataProvider

// This should be QWidget, not QDialog
Expand All @@ -432,44 +357,37 @@ QWidget* QgsProviderRegistry::selectWidget( const QString & providerKey,
return selectFactory( parent, fl );
}

void * QgsProviderRegistry::function( QString const & providerKey,
QString const & functionName )
void *QgsProviderRegistry::function( QString const & providerKey,
QString const & functionName )
{
QString lib = library( providerKey );

QLibrary* myLib = new QLibrary( lib );
QLibrary myLib( library( providerKey ) );

QgsDebugMsg( "Library name is " + myLib->fileName() );
QgsDebugMsg( "Library name is " + myLib.fileName() );

bool loaded = myLib->load();

if ( loaded )
if ( myLib.load() )
{
void * ptr = myLib->resolve( functionName.toAscii().data() );
delete myLib;
return ptr;
return myLib.resolve( functionName.toAscii().data() );
}
else
{
QgsDebugMsg( "Cannot load library: " + myLib.errorString() );
return 0;
}
QgsDebugMsg( "Cannot load library: " + myLib->errorString() );
delete myLib;
return 0;
}

QLibrary *QgsProviderRegistry::providerLibrary( QString const & providerKey ) const
{
QString lib = library( providerKey );

QLibrary *myLib = new QLibrary( lib );
QLibrary *myLib = new QLibrary( library( providerKey ) );

QgsDebugMsg( "Library name is " + myLib->fileName() );

bool loaded = myLib->load();

if ( loaded )
{
if ( myLib->load() )
return myLib;
}

QgsDebugMsg( "Cannot load library: " + myLib->errorString() );

delete myLib;

return 0;
}

Expand Down Expand Up @@ -508,7 +426,6 @@ QString QgsProviderRegistry::protocolDrivers() const
return mProtocolDrivers;
}


QStringList QgsProviderRegistry::providerList() const
{
QStringList lst;
Expand All @@ -519,7 +436,6 @@ QStringList QgsProviderRegistry::providerList() const
return lst;
}


const QgsProviderMetadata* QgsProviderRegistry::providerMetadata( const QString& providerKey ) const
{
return findMetadata_( mProviders, providerKey );
Expand Down