smf/smfservermodule/smfserver/pluginmgr/smfpluginmanager.cpp
author cgandhi
Mon, 11 Oct 2010 21:59:54 +0530
changeset 26 83d6a149c755
parent 25 a180113055cb
permissions -rw-r--r--
Submitting following changes - AuthApps for Last.fm and Twitter added API for checking ServiceAuthorization added for SMFCredMgrClient API added for forcefully removing credential details from SMFCredMgr Extra argument checks in SMfClient APIs APIs for service login and logout from SMFClient Redundant members removed from SmfServerSymbian DSM bug fixes Test Apps included

/**
 * Copyright (c) 2010 Sasken Communication Technologies Ltd.
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of the "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:
 * Chandradeep Gandhi, Sasken Communication Technologies Ltd - Initial contribution
 *
 * Contributors:
 * Manasij Roy, Nalina Hariharan
 * 
 * Description:
 * The Plugin Manager class manages the loading and unloading of plug-ins
 *
 */

#include <QDir>
#include <QDebug>
#include <QLibraryInfo>
#include <QFileSystemWatcher>
#include <QPluginLoader>
#include <QList>
#include <smfpluginbase.h>
#include <smfpluginutil.h>
#include <smfprovider.h>
#include <smfcredmgrclient.h>

#include "smfpluginmanager.h"
#include "smfpluginmanagerutil.h"
#include "smftransportmanagerutil.h"

// Static data initialisation
SmfPluginManager* SmfPluginManager::m_myInstance = NULL;


/**
 * Method to get the instance of SmfPluginManager class
 * @param aServer The Smf server instance
 * @return The instance of SmfPluginManager class
 */
SmfPluginManager* SmfPluginManager::getInstance ( SmfServer *aServer)
	{
	if(NULL == m_myInstance)
		m_myInstance = new SmfPluginManager(aServer);
	return m_myInstance;
	}


/**
 * Constructor with default argument
 * @param aServer The Smf server instance
 */
SmfPluginManager::SmfPluginManager ( SmfServer *aServer )
	{
	// Save the server instance
	m_server = aServer;
	
	// initialize the file watcher to monitor plugin addition/upgradation/removal
	initializeFileWatcher ( );
	
	// create a database to store the folder structure of the path "c://resource//qt//plugins"
	initializeSmfPluginDataBase ( );
	
	// create teh Plugin Manager utility class instance
	m_util = new SmfPluginManagerUtil(this);
	
	// Get handle to the Transport MAnager utility instance
	m_transMngrUtil = SmfTransportManagerUtil::getInstance();
	}


/**
 * Destructor
 */
SmfPluginManager::~SmfPluginManager ( )
	{
	qDebug()<<"Inside SmfPluginManager::~SmfPluginManager()";
	
	// delete file watcher
	if(m_fileWatcher)
		delete m_fileWatcher;
	
	if(m_tempStruct)
		delete m_tempStruct;
	
	// delete the plugin information hash
	if(m_waitingPluginHash.count() > 0)
		{
		foreach(SmfWaitingPluginInfoStruc *str, m_waitingPluginHash.values())
			delete str;
		}
	
	// delete the SmfPluginManagerUtil class instance
	if(m_util)
		delete m_util;
	
	// Close the database
	if(m_pluginDataBase.isOpen())
		{
		m_pluginDataBase.close();
		m_pluginDataBase.removeDatabase("SmfPluginsInfoDatabase");
		QFile::remove("SmfPluginsInfoDatabase");
		}
	
	// unload all loaded plugins
	unload(m_pluginLoaderHash.keys());
	
	// Finally remove the existing singleton instance of plugin manager itself
	if(m_myInstance)
		delete m_myInstance;
	}


/**
 * Method called by Smf server to create a web query.
 * Plugin Manager calls the appropriate web query creation method 
 * using the aOperation and aInputData parameters. Once the web request 
 * is ready, it calls the appropriate methods exposed by the Transport 
 * Manager to send the network request.
 * @param aSessionID The session ID provided by Smf Server
 * @param aPluginID The plugin ID that need to perform this operation
 * @param aOperation The type of operation to be performed
 * @param aInputData The data required to create the web query
 * @return SmfError The result of the operation. It can be :-
 * SmfPluginNoError (if the request is sent successfully) or 
 * SmfPluginLoadError (if plugin could not be loaded) or
 * SmfPluginNotAuthorised (if the plugin is not authorised) or
 * SmfPluginUnknownPluginService (if the requested service is not known or unsupported) or
 * SmfPluginRequestCreationFailed (if request creation has failed) or
 * SmfPluginSOPCheckFailed (if plugins request doesnot comply to the Same Origin Policy) or
 * SmfPluginRequestSendingFailed (if request could not be sent) or 
 * SmfPluginUnknownHttpService (if the plugin requested any unknown http 
 * method other than get, post, put, head or delete)  
 */
SmfError SmfPluginManager::createRequest ( const quint32& aSessionID, 
		const QString& aPluginID, 
		const SmfRequestTypeID& aOperation, 
		QByteArray& aInputData )
	{
	qDebug()<<"Inside SmfPluginManager::createRequest()";
	
	SmfError result = SmfUnknownError;

	// Load the plugin
	QObject *plugin = load(aPluginID, result);
	
	// Check if plugin is loaded
	if(plugin && (SmfNoError == result))
		{
		SmfPluginBase* instance = qobject_cast<SmfPluginBase *>(plugin);
		
		if(instance)
		{
		QList<QUrl> urlList;
		SmfPluginRequestData reqData;

		// check if the plugin is authorised (with CSM)
		if( authorisePlugin(aPluginID, urlList ))
			{
			qDebug()<<"Plugin authorised";
			
			// call the utility method to create plugin specific request
			result = SmfUnknownError;
			QByteArray notused;
			m_util->createRequest(plugin, aOperation, aInputData, reqData, result, notused);

			// If the request is created successfully, call the TM method to send the request
			if( SmfNoError == result )
				{
				qDebug()<<"Plugin request creation successful";
				m_tempStruct = new SmfWaitingPluginInfoStruc();
				m_tempStruct->iSessionID = aSessionID;
				m_tempStruct->iPluginId = aPluginID;
				m_tempStruct->iInstance = instance;
				m_tempStruct->iOperation = aOperation;
				m_tempStruct->iInputData = aInputData;
			
				// send the request
				sendRequest ( reqData, result, urlList );
				}
				else
					qDebug()<<"Plugin request creation failed!!!, error = "<<result;
			}
		
		else
			{
			// plugin not authorised, so unload
			qDebug()<<"Plugin not authorised!!!";
			unload(instance);
				result = SmfPMPluginNotAuthorised;
			}
		}
		else
			{
			// plugin instance cannot be casted, so unload
			qDebug()<<"Plugin instance cannot be casted to SmfPluginBase*!!!";
			unload(instance);
			result = SmfPMPluginLoadError;
			}
		}

	else
		{
		// plugin not loaded
		qDebug()<<"Plugin not loaded!!!";
		}
	
	return result;
	}


/**
 * Method called by Smf server to create a synchronous plugin request.
 * @param aPluginID The plugin ID that need to perform this operation
 * @param aOperation The type of operation to be performed
 * @param aInputData The data required by the plugins
 * @param aOutputData [out] The output data to be filled by the plugins
 * @return SmfError The result of the operation. It can be :-
 * SmfPluginNoError (if the request is success) or 
 * SmfPluginLoadError (if plugin could not be loaded) or
 * SmfPluginNotAuthorised (if the plugin is not authorised) or
 * SmfPluginUnknownPluginService (if the requested service is not known or unsupported)
 */
SmfError SmfPluginManager::createSyncRequest ( const QString& aPluginID, 
		const SmfRequestTypeID& aOperation, 
		QByteArray& aInputData,
		QByteArray& aOutputData )
	{
	qDebug()<<"Inside SmfPluginManager::createSyncRequest()";
	
	SmfError result = SmfUnknownError;

	// Load the plugin
	QObject *plugin = load(aPluginID, result);
	
	// Check if plugin is loaded
	if(plugin && (SmfNoError == result))
		{
		SmfPluginBase* instance = qobject_cast<SmfPluginBase *>(plugin);
		
		if(instance)
		{
		QList<QUrl> urlList;
		SmfPluginRequestData reqData;

		// check if the plugin is authorised (with CSM)
		if( authorisePlugin(aPluginID, urlList ))
			{
			qDebug()<<"Plugin authorised";
			
			// call the utility method to create plugin specific request
			result = SmfUnknownError;
			m_util->createRequest(plugin, aOperation, aInputData, reqData, result, aOutputData );

			// If the request is created successfully, call the TM method to send the request
			if( SmfNoError == result )
				qDebug()<<"Plugin request creation successful";
			else
				qDebug()<<"Plugin request creation failed!!!, error = "<<result;
			}
		
		else
			{
			// plugin not authorised, so unload
			qDebug()<<"Plugin not authorised!!!";
			unload(instance);
				result = SmfPMPluginNotAuthorised;
			}
		}
		else
			{
			// plugin instance cannot be casted, so unload
			qDebug()<<"Plugin instance cannot be casted to SmfPluginBase*!!!";
			unload(instance);
			result = SmfPMPluginLoadError;
			}
		}

	else
		{
		// plugin not loaded
		qDebug()<<"Plugin not loaded!!!";
		}
	
	return result;
	}



/**
 * Method called by Transport Manager when network response is available
 * @param aTransportResult The result of Transport Operation
 * @param aReply The QNetworkReply instance that requested 
 * this transaction
 * @param aResponse The network response data, may be NULL for error
 */
void SmfPluginManager::responseAvailable ( 
		const SmfTransportResult &aTransportResult, 
		QNetworkReply *aReply,
		QByteArray *aResponse )
	{
	qDebug()<<"Inside SmfPluginManager::responseAvailable()";
		
	// get the details of the plugin which made this request
	SmfWaitingPluginInfoStruc* info = NULL;
	info = m_waitingPluginHash.value(aReply);
	
	if(info)
			{
			quint32 sessionId = m_waitingPluginHash.value(aReply)->iSessionID;
			QString pluginId = m_waitingPluginHash.value(aReply)->iPluginId;
			SmfRequestTypeID operation = m_waitingPluginHash.value(aReply)->iOperation;
			QByteArray inputData = m_waitingPluginHash.value(aReply)->iInputData;
			
			QVariant result;
			SmfPluginRetType retType = SmfRequestError;
			SmfResultPage pageResult;
			
			// call the utility method to send response to appropriate plugins
			SmfError retValue = m_util->responseAvailable( info->iInstance, operation, 
					aTransportResult, aResponse, &result, retType, pageResult );
			
			qDebug()<<"m_util->responseAvailable() return = "<<retValue;
		
			// remove the plugin from the waiting list
			delete m_waitingPluginHash.value(aReply);
			m_waitingPluginHash.remove(aReply);
		
			QByteArray arr;
			QDataStream stream(&arr, QIODevice::ReadWrite);
		
			if( SmfNoError == retValue )
				{
				qDebug()<<"Parsing of response is successful";
				
				// serialize the response to suitable class and pass the data to server
				serializeResult(operation, &result, stream);
			
				// Send the response data to the server
				m_server->resultsAvailable(sessionId, &arr, retValue);
				}
		
			// Send the request again
			else if( SmfPMPluginSendRequestAgain == retValue )
				{
				qDebug()<<"Send request again";
				retValue = createRequest( sessionId, pluginId, operation, inputData );
				}
			
			// Error
			else
				{
				qDebug()<<"Plugin responseAvailable() failed!!!, error = "<<retValue;
				
				// Error in parsing, sent to server
				stream<<result.toString();
				m_server->resultsAvailable(sessionId, &arr, retValue);
			}
		}
	else
		qDebug()<<"No outstanding requests for this QNetworkReply!!!";
		
	// delete aReply later, when event loop is re-entered
	aReply->deleteLater();
	}
	

/**
 * Method to cancel the service request
 * @param aSessionID The session to be cancelled.
 * If the plugin is not loaded currently, this method just returns true.
 * @return Returns true if the plugin operation could be cancelled 
 * else returns false.
 */
bool SmfPluginManager::cancelRequest (  const quint32& aSessionID )
	{
	bool retValue = true;
	qDebug()<<"Inside SmfPluginManager::cancelRequest()";
	
	// Get the plugin for which cancel is requested
	foreach(SmfWaitingPluginInfoStruc* iPluginInfo, m_waitingPluginHash.values())
		{
		if( aSessionID == iPluginInfo->iSessionID )
			{
			qDebug()<<"Plugin to be cancelled found in the waiting list";
			
			// Notify Transport Manager
			m_transMngrUtil->cancelRequest(m_waitingPluginHash.key(iPluginInfo));
			
			}
		else
			retValue =  true;
		}
	return retValue;
	}


/**
 * Method called to initialize the file watcher watching the file  
 * system for adition/upgradation/removal of plugins
 */
void SmfPluginManager::initializeFileWatcher ( )
	{
	qDebug()<<"Inside SmfPluginManager::initializeFileWatcher()";
	
	// Create the file watcher for the plugins in /Smf folder of the Qt plugin directory
	m_fileWatcher = new QFileSystemWatcher(this);
	
	// Get the directory having the Qt plugin stubs
	QDir dir(QLibraryInfo::location(QLibraryInfo::PluginsPath));
	
	// If Smf folder exists
	if(dir.cd("smf/plugin"))
		{
		// Add each service provider folders to the file watcher
		foreach(QString folder, dir.entryList(QDir::AllDirs))
			{
			dir.cd(folder);
			m_fileWatcher->addPath(dir.absolutePath());
			dir.cdUp();
			}
		}
	else
		m_fileWatcher->addPath(dir.absolutePath());
	
	connect(m_fileWatcher, SIGNAL(directoryChanged(const QString&)), 
			this, SLOT (directoryChanged(const QString&)));
	
	connect(m_fileWatcher, SIGNAL(fileChanged(const QString&)), 
				this, SLOT (directoryChanged(const QString&)));
	}



/**
 * Method called to initialize the database holding the plugin 
 * directory sructure information. This is called only once when 
 * the Plugin Manager is instantiated.
 * This method creates and updates m_pluginIdPathHash member 
 * of this class
 * @return Returns true the database is successfully created and updated, 
 * else returns false
 */
bool SmfPluginManager::initializeSmfPluginDataBase ( )
	{
	qDebug()<<"Inside SmfPluginManager::initializeSmfPluginDataBase()";
	
	// Find QSQLite driver and create a connection to database
	QFile::remove("SmfPluginsInfoDatabase");
	m_pluginDataBase = QSqlDatabase::addDatabase("QSQLITE");
	m_pluginDataBase.setDatabaseName("SmfPluginsInfoDatabase");
	
	// Open the database
	bool opened = m_pluginDataBase.open();
	if(!opened)
		{
		qDebug()<<"Database could not be opened, returning !!!";	
		return false;
		}
#ifdef DETAILEDDEBUGGING
	qDebug()<<"Database opened";
#endif
	
	// Create a query to create the DB table for Plugin Manager (if it doesn't exists)
	QSqlQuery query;
	bool tableCreated = false;

	tableCreated = query.exec("CREATE TABLE IF NOT EXISTS pluginDetails ("
			"pluginId TEXT PRIMARY KEY, interfaceName TEXT, serviceProvider TEXT, "
			"description TEXT, serviceUrl TEXT, authAppId TEXT, authAppName TEXT)");

	// Error - table not created, Plugin Manager might not work properly
	if(!tableCreated)
		{
		qDebug()<<"Table not created!!!, error = "<<query.lastError().text();
		
		// Close the database
		m_pluginDataBase.close();
		return false;
		}
#ifdef DETAILEDDEBUGGING
	qDebug()<<"Table created";
#endif
	
	// Get the directory having the Qt plugin stubs
	QDir dir(QLibraryInfo::location(QLibraryInfo::PluginsPath));
	
	// If Smf folder exists
	if(dir.cd("smf/plugin"))
		{
#ifdef DETAILEDDEBUGGING
		qDebug()<<"Smf/plugin folder exists";
#endif
		// Get each interface folders names
		foreach(QString intfName, dir.entryList(QDir::AllDirs))
			{
			dir.cd(intfName);
#ifdef DETAILEDDEBUGGING
			qDebug()<<"Interface name : "<<dir.dirName();
#endif
			
			// Get each plugin in this folder
			foreach(QString pluginName, dir.entryList(QDir::Files))
				{
#ifdef DETAILEDDEBUGGING
				qDebug()<<"plugins for this Interface : "<<pluginName;
#endif
				
				// load this plugin
				QPluginLoader pluginLoader(dir.absoluteFilePath(pluginName));
				QObject *instance = pluginLoader.instance();
				if (instance)
					{
#ifdef DETAILEDDEBUGGING
					qDebug()<<"instance found";
#endif
					SmfPluginBase* plugin = qobject_cast<SmfPluginBase *>(instance);
				    if (plugin)
				    	{
#ifdef DETAILEDDEBUGGING
						qDebug()<<"SmfPluginBase found";
#endif
						plugin->initialize();
				    
						// get the plugin id
						QString id = plugin->getProviderInfo()->pluginId();
						
						// get the interface implemented by the plugin
						QString intfImplemented = dir.dirName();
						intfImplemented.prepend("org.symbian.smf.plugin.");
#ifdef DETAILEDDEBUGGING
						qDebug()<<"intfImplemented = "<<intfImplemented;
#endif
						
						// get the service provider
						QString serProv = plugin->getProviderInfo()->serviceName();
						
						//get the description
						QString desc = plugin->getProviderInfo()->description();
						
						// get the service URL
						QString servURL = plugin->getProviderInfo()->serviceUrl().toString();
						
						// get the auth application process name
						QString authAppName = plugin->getProviderInfo()->authenticationAppName();
								
						// get the authentication application id
						QString str;
						QStringList list;
						QString authAppId = plugin->getProviderInfo()->authenticationApp(
								str, list, QIODevice::ReadWrite);
						
						// Update m_pluginIdPathHash
						m_pluginIdPathHash.insert(id, dir.absoluteFilePath(pluginName));
						
						QSqlQuery rowInsertQuery;
						
						// insert into database
						bool rowInserted = rowInsertQuery.exec(QString("INSERT INTO pluginDetails VALUES ("
								"'%1', '%2', '%3', '%4', '%5', '%6', '%7')").arg(id).arg(intfImplemented)
								.arg(serProv).arg(desc).arg(servURL).arg(authAppId).arg(authAppName));
						
						if(rowInserted)
							qDebug()<<QString("This Plugin's information is added to database : '%1' '%2' '%3' '%4'")
											.arg(id).arg(intfImplemented).arg(serProv).arg(authAppId);
						else
							{
							qDebug()<<"Data base insert statement returned = "<<rowInserted;
							if(0 != query.lastError().text().size())
								qDebug()<<"plugins data not written to database!!!, error = "<<query.lastError().text();
							}
				    	}
				    else
				    	{
						qDebug()<<"Plugin could not be converted to SmfpluginBase* - returning!!!";
						
						// Close the database
						m_pluginDataBase.close();
						
				    	return false;
				    	}
				    
				    pluginLoader.unload();
					}
				else
					{
					qDebug()<<"Plugin could not be loaded - returning!!!, error = "<<pluginLoader.errorString();
					
					// Close the database
					m_pluginDataBase.close();
										
					return false;
					}
				}
			dir.cdUp();
			}
		}
	else
		{
			qDebug()<<"No Smf plugins installed!!!";
			return false;
		}
	
	
	// Close the database
	m_pluginDataBase.close();
	
	return true;
	}



/**
 * Method to load a plugin using its Plugin Id.
 * @param aPluginId The unique ID of the plugin 
 * @param aLoadResult [out] Output paramater indicating the result 
 * of the loading. It can be:-
 * SmfPluginNoError (if plugin was loaded successfully) or
 * SmfPluginNotFound (if plugin with the given id could not be found) 
 * SmfPluginNotLoaded (if plugin could not be loaded) or 
 * @return The instance of the loaded plugin if loaded, else NULL
 */
QObject* SmfPluginManager::load ( const QString &aPluginId,
		SmfError &aLoadResult)
	{
	qDebug()<<"Inside SmfPluginManager::load()";
	
	// Find the plugin Path
	QString pluginPath = m_pluginIdPathHash.value(aPluginId);
	
	if(!pluginPath.isEmpty())
		{
		// create the plugin loader and load the plugin
		QPluginLoader *pluginLoader = NULL;
		pluginLoader = new QPluginLoader(pluginPath);
		if(!pluginLoader)
			{
			// Plugin loader could not be created, error
			qDebug()<<"QPluginLoader allocation failed!!!";
			aLoadResult = SmfPMPluginNotLoaded;
			return NULL;
			}
		
		SmfPluginBase *plugin = qobject_cast<SmfPluginBase *>(pluginLoader->instance());
		
		// If the plugin is loaded
		if( pluginLoader->isLoaded() && plugin )
			{
			// Initialize the plugin
			plugin->initialize();
			
			// update the plugin loader and the loaded plugin lists
			m_pluginLoaderHash.insertMulti(plugin, pluginLoader);
			aLoadResult = SmfNoError;
			qDebug()<<"Plugin loaded";
			return pluginLoader->instance();
			}
		else
			{
			// Plugin could not be loaded, error
			qDebug()<<"Plugin not loaded!!!, error = "<<pluginLoader->errorString();
			aLoadResult = SmfPMPluginNotLoaded;
			return NULL;
		}
		}
	else
		{
		// plugin could not be found in the hash maintained by PM
		qDebug()<<"Plugin not found!!!";
		aLoadResult = SmfPMPluginNotFound;
		return NULL;
		}
	}


/**
 * Method to unload a loaded plugin. Returns true if success, else 
 * returns false.
 * @param aPlugin The plugin instance to be unloaded
 * @return Returns true if the mentioned plugin could be unloaded. Returns 
 * false, if the plugin instance is NULL, or if it could not be unloaded.
 */
bool SmfPluginManager::unload ( SmfPluginBase *aPlugin )
	{
	qDebug()<<"Inside SmfPluginManager::unload()";
	bool unloadResult = true;
	
	if(aPlugin)
		{
		// Get all the loaders for this plugin
		QList<QPluginLoader*> loaderList = m_pluginLoaderHash.values(aPlugin);
		if(loaderList.size())
			{
			foreach(QPluginLoader *loader, loaderList)
				{
				// for each loader unload the plugin
				unloadResult = loader->unload();
				
				// delete the instance of the loader
				delete loader;
				loader = NULL;
				}
			
			// Remove the plugin and its associated loaders from the Hash
			m_pluginLoaderHash.remove(aPlugin);
			return unloadResult;
			}
		}
	else
		{
		qDebug()<<"Plugin  instance is NULL!!!";
		unloadResult = false;
		}
	
	return unloadResult;
	}


/**
 * Method to unload the list of loaded plugins. Returns true if all unload 
 * are success, else returns false if any one fails.
 * @param aPluginList The list of instances for all plugins that are 
 * to be unloaded. This method does nothing and returns false if the list is empty.
 * @return Returns true if all are success, else returns false if any 
 * one fails. Also returns false if the input list is empty.
 */
bool SmfPluginManager::unload ( const QList<SmfPluginBase *> &aPluginList)
	{
	qDebug()<<"Inside SmfPluginManager::unload() - overloaded fn";
	bool unloaded = false;
	
	if(aPluginList.size())
		{
		//unload all the required plugins
		foreach(SmfPluginBase *plugin, aPluginList)
			{
			// unload individual plugins in the list
			bool ret = unload(plugin);
			
			// indicate error if any one of the plugin failed to unload
			if(!ret)
				unloaded = ret;
			}
		}
	return unloaded;
	}


/**
 * Method that calls the Transport Manager Utility class method to 
 * send the request created by the plugins over the network
 * @param aReqData The request data created by the plugin
 * @param aResult [out] The output parameter indicating the result 
 * of this method. This can be :-
 * SmfPluginNoError (if the request is sent successfully) or 
 * SmfPluginSOPCheckFailed (if plugins request doesnot comply to 
 * the Same Origin Policy) or 
 * SmfPluginRequestSendingFailed (if request could not be sent) or 
 * SmfPluginUnknownHttpService (if the plugin requested any unknown http 
 * method other than get, post, put, head or delete)  
 * @param aUrlList The list of accessible Urls for this plugin
 */
void SmfPluginManager::sendRequest ( SmfPluginRequestData &aReqData, 
		SmfError &aResult,
		const QList<QUrl> &aUrlList )
	{
	qDebug()<<"Inside SmfPluginManager::sendRequest()";
	
	QNetworkReply* reply;
	bool sopCompliant = false;
	
	// Check the type of Http operation to be performed
	switch(aReqData.iHttpOperationType)
		{
		// Http HEAD
		case QNetworkAccessManager::HeadOperation:
#ifdef DETAILEDDEBUGGING
			qDebug()<<"http::head Operation requested";
#endif
			reply = m_transMngrUtil->head(aReqData.iNetworkRequest, aUrlList, sopCompliant);
			break;
		
		// Http GET
		case QNetworkAccessManager::GetOperation:
#ifdef DETAILEDDEBUGGING
			qDebug()<<"http::get Operation requested";
#endif
			reply = m_transMngrUtil->get(aReqData.iNetworkRequest, aUrlList, sopCompliant);
			break;
			
		// Http PUT	
		case QNetworkAccessManager::PutOperation:
#ifdef DETAILEDDEBUGGING
			qDebug()<<"http::put Operation requested";
#endif
			reply = m_transMngrUtil->put(aReqData.iNetworkRequest, aReqData.iPostData->buffer(), aUrlList, sopCompliant);
			delete aReqData.iPostData;
			break;
			
		// Http POST
		case QNetworkAccessManager::PostOperation:
#ifdef DETAILEDDEBUGGING
			qDebug()<<"http::post Operation requested";
#endif
			reply = m_transMngrUtil->post(aReqData.iNetworkRequest, aReqData.iPostData->buffer(), aUrlList, sopCompliant);
			delete aReqData.iPostData;
			break;
			
		// Http DELETE
		case QNetworkAccessManager::DeleteOperation:
#ifdef DETAILEDDEBUGGING
			qDebug()<<"http::delete Operation requested";
#endif
			reply = m_transMngrUtil->deleteResource(aReqData.iNetworkRequest, aUrlList, sopCompliant);
			break;
			
		default:
#ifdef DETAILEDDEBUGGING
			qDebug()<<"unknown http Operation requested!!!";
#endif
			aResult = SmfPMPluginUnknownHttpService;
			return;
		}
	
	if( sopCompliant )
		{
		if( reply )
			{
			// SOP compliant, sending successful
			qDebug()<<"No error, request sent";
			m_waitingPluginHash.insert(reply, m_tempStruct);
			m_tempStruct = NULL;
			aResult = SmfNoError;
			}
		else
			{
			// reply is NULL, sending failed
			qDebug()<<"QNetworkReply returned NULL - request not sent";
			aResult = SmfPMPluginRequestSendingFailed;
			}
		}
	
	else
		{
		// SOP violation
		qDebug()<<"SOP checking failed";
		aResult = SmfPMPluginSOPCheckFailed;
		}
	}


/**
 * Method that checks if a plugin is authorised to make a request. 
 * This method communicates with Credential and Settings Manager 
 * through Smf server, giving the registration token and getting 
 * the valid url list if available for this plugin.
 * @param aPluginId The ID of the plugin
 * @param aUrlList [out] The list of Urls that the plugin can send 
 * request to (to be filled by CSM). This list will be empty if 
 * aPluginId is not valid or not authorised.
 * @return Returns true if plugin is authorised, else returns false.
 * Also returns false if aRegToken is empty.
 */
bool SmfPluginManager::authorisePlugin( const QString &aPluginId, 
		QList<QUrl> &aUrlList )
	{
	qDebug()<<"Inside SmfPluginManager::authorisePlugin()";
	
	bool authorised = false;
	SmfCredMgrClient csmClient;
	
	aUrlList = csmClient.URLList(aPluginId);
	if(aUrlList.count())
		authorised = true;
	
	return authorised;
	}


/**
 * Method to serialize the result of parsing (which is done by the 
 * plugins) to QByteArray to be sent to Smf server.
 * @param aOperation The type of operation to be performed
 * @param aResult The data to be serialized (should not be NULL)
 * @param aDataStream Stream to be written to
 */
void SmfPluginManager::serializeResult ( 
		const SmfRequestTypeID &aOperation, 
		QVariant* aResult,
		QDataStream &aDataStream )
	{
	qDebug()<<"Inside SmfPluginManager::serializeResult()";
	
	// Call the utlity class method to serialize the result
	m_util->serializeResult(aOperation, aResult, aDataStream);
	}


/**
 * Method for the directoryChanged signal of QFileSystemWatcher.
 * This will update the iPluginHash member and also the Plugin 
 * Information List.
 * @param aPath The path of the directory that has changed
 */
void SmfPluginManager::directoryChanged ( const QString &aPath )
	{
	qDebug()<<"Inside SmfPluginManager::directoryChanged()";
	qDebug()<<"Changed path = "<<aPath;
	
	// Create a QDir instance with the given path
	QDir dir(aPath);
	QString pluginId;
	QString oldpluginId;
	QString interfaceName;
	QString serviceProv;
	QString authAppId;
	QString authAppName;

	// Get all the files in the directory at a specified path(sorted)
	QStringList newPlugins = dir.entryList(QDir::Files, QDir::Name);
	QStringList::const_iterator newListIterator = newPlugins.constBegin();
	
	foreach(QString name, newPlugins)
		qDebug()<<"New plugin = "<<name;
	
	// Get all plugins who were in this path, before this directory was changed
	QStringList availablePlugins = m_pluginIdPathHash.keys(aPath);
	availablePlugins.sort();
	QStringList::const_iterator oldListIterator = availablePlugins.constBegin();
	
	foreach(QString name, availablePlugins)
		qDebug()<<"Old plugin = "<<name;
	
	// Open the database
	bool opened = m_pluginDataBase.open();
	if(!opened)
		return;
	
	// If plugin is changed
	if( newPlugins.count() == availablePlugins.count() )
		{
		qDebug()<<"Plugin upgraded...";
		// Check for equality
		while( newListIterator != newPlugins.constEnd() )
			{
			if( *newListIterator == *oldListIterator )
				{
				newListIterator++;
				oldListIterator++;
				}
			else
				break;
			}
		// replace *oldListIterator with *newListIterator
		QHash<QString, QString>::iterator i = m_pluginIdPathHash.find(*oldListIterator);
		m_pluginIdPathHash.insert(*newListIterator, i.value());
		m_pluginIdPathHash.remove(*oldListIterator);
		
		// Also update database with *newListIterator
	    QSqlQuery updateQuery;
	    
	    bool updated = updateQuery.exec(QString("UPDATE pluginDetails SET pluginId = '%1' "
	    		"WHERE pluginId = '%2'").arg(*newListIterator).arg(*oldListIterator));
	    if (!updated)
	    	if(0 != updateQuery.lastError().text().size())
	    		qDebug()<<"Database table not updated, error = "<<updateQuery.lastError().text();
		
		// Get the new and old plugin Ids
		pluginId = *newListIterator;
		oldpluginId = *oldListIterator;
		
		// Load the plugin and get its service provider name
		SmfError result;
		SmfPluginBase* instance = qobject_cast<SmfPluginBase *>(load(pluginId, result));
		
		if(instance && (SmfNoError == result))
			{
			instance->initialize();
			serviceProv = instance->getProviderInfo()->serviceName();
			interfaceName = dir.dirName();
			}
		
		unload(instance);
		
		qDebug()<<QString("Upgraded plugin details are : '%1' '%2' '%3' '%4'").arg(oldpluginId)
				.arg(pluginId).arg(interfaceName).arg(serviceProv);
		
		// Inform server that plugin has been changed
#ifdef CSM_INTEGRATED
		//Remove after Server Integration
		m_server->pluginChanged(oldPluginId, pluginId, interfaceName, serviceProv);
#endif
		}
		
	// If plugin is added
	else if(newPlugins.count() > availablePlugins.count())
		{
		qDebug()<<"Plugin Added...";
		// Check for equality
		while( oldListIterator != availablePlugins.constEnd() )
			{
			if( *newListIterator == *oldListIterator )
				{
				newListIterator++;
				oldListIterator++;
				}
			else
				break;
			}
		// replace *oldListIterator with *newListIterator
		m_pluginIdPathHash.insert(*newListIterator, aPath);
		
		// Get the plugin Id
		pluginId = *newListIterator;
		
		// Load the plugin and get its service provider name
		SmfError result;
		SmfPluginBase* instance = qobject_cast<SmfPluginBase *>(load(pluginId, result));
		
		if(instance && (SmfNoError == result))
			{
			instance->initialize();
			serviceProv = instance->getProviderInfo()->serviceName();
			interfaceName = dir.dirName();
			interfaceName.prepend("org.symbian.smf.plugin.");
			QString prgm;
			QStringList list;
			authAppId = instance->getProviderInfo()->authenticationApp(prgm, list, QIODevice::ReadWrite);
			authAppName = instance->getProviderInfo()->authenticationAppName();
			}
		
		unload(instance);
		
		// Also add to the database the value newListIterator and aPath
		QSqlQuery insertRowQuery;
		bool rowInserted = insertRowQuery.exec(QString("INSERT INTO pluginDetails VALUES "
				"('%1', '%2', '%3', '%4', '%5')").arg(pluginId).arg(interfaceName).arg(serviceProv).arg(authAppId).arg(authAppName));

		 // Error
		if (!rowInserted)
			qDebug()<<"Database table not inserted, error = "<<insertRowQuery.lastError().text();
		
		qDebug()<<QString("Added plugin detailes are : '%1' '%2' '%3'").arg(pluginId)
				.arg(interfaceName).arg(serviceProv);
		
		// Inform server that plugin has been added
#ifdef CSM_INTEGRATED
		//Remove after Server Integration
		m_server->pluginAdded(pluginId, interfaceName, serviceProv);
#endif
		}
	
	// If plugin is removed
	else //for newPlugins.count() < availablePlugins.count()
		{
		qDebug()<<"Plugin removed...";
		
		// Check for equality
		while( newListIterator != newPlugins.constEnd() )
			{
			if( *newListIterator == *oldListIterator )
				{
				newListIterator++;
				oldListIterator++;
				}
			else
				break;
			}
		// remove *oldListIterator
		m_pluginIdPathHash.remove(*oldListIterator);
		
		// Also remove oldListIterator from the database
		QSqlQuery deleteRowQuery;
		bool rowDeleted = deleteRowQuery.exec(QString("DELETE FROM pluginDetails WHERE pluginId = '%1'")
				.arg(*oldListIterator));
		 
		// Error
		if (!rowDeleted)
			qDebug()<<"Database table row not deleted, error = "<<deleteRowQuery.lastError().text();
		
		// Get the plugin Id
		pluginId = *oldListIterator;
		
		// Load the plugin and get its service provider name
		SmfError result;
		SmfPluginBase* instance = qobject_cast<SmfPluginBase *>(load(pluginId, result));
		
		if(instance && (SmfNoError == result))
			{
			instance->initialize();
			serviceProv = instance->getProviderInfo()->serviceName();
			interfaceName = dir.dirName();
			}
		
		unload(instance);
		
		qDebug()<<QString("Added plugin detailes are : '%1' '%2' '%3'").arg(pluginId)
				.arg(interfaceName).arg(serviceProv);
		
		// Inform server that plugin has removed
#ifdef CSM_INTEGRATED
		//Remove after Server Integration
		m_server->pluginRemoved(pluginId, interfaceName, serviceProv);
#endif
		}
	// Close the database
	m_pluginDataBase.close();
	}


/**
 * Method to get the list of the SmfProvider for all the plugins that implement 
 * the mentioned Interface 
 * @param aInterface The interface for which list of plugins is required 
 * @param aMap The map of pluginID and its corresponding SmfProvider. The Map 
 * will be empty if no plugins for the given interface could be found.
 */
void SmfPluginManager::getPlugins(const QString& aInterface, QMap<QString,SmfProvider>& aMap)
	{
	qDebug()<<"Inside SmfPluginManager::getPlugins()";
	qDebug()<<"Argument, intf name = "<<aInterface;
	
	aMap.clear();
	
	if(aInterface.isEmpty())
		{
		qDebug()<<"Interface name is empty!!!";
		return;
		}
	
	// Open the database
	bool opened = m_pluginDataBase.open();
	if(!opened)
		{
		qDebug()<<"Data base not opened, exiting getplugins()!!!";
		return;
		}
#ifdef DETAILEDDEBUGGING
	qDebug()<<"Data base opened";
#endif
	
	// Query the database for all pluginIDs that implement the given interface
	QSqlQuery query(QString("SELECT pluginId, interfaceName, serviceProvider, description, "
			"serviceUrl, authAppId, authAppName FROM pluginDetails where interfaceName = '%1'").arg(aInterface));
	
	while(query.next())
		{
#ifdef DETAILEDDEBUGGING
		qDebug()<<"Query is success";
#endif

		SmfProvider prov;
		
		// get the pluginId
		QString pluginId = query.value(0).toString();
		qDebug()<<"Found Plugin Id = "<<pluginId;
		
		// get the service type / interface name
		QStringList servicetypes;
		servicetypes.insert(0, query.value(1).toString());
		prov.setSupportedInterfaces(servicetypes);
#ifdef DETAILEDDEBUGGING
		qDebug()<<"  Its interface = "<<servicetypes.at(0);
#endif
		
		// Get the serv provider
		QString servName = query.value(2).toString();
		prov.setServiceName(servName);
#ifdef DETAILEDDEBUGGING
		qDebug()<<"  Its serv prov = "<<servName;
#endif
		
		// Get the description
		QString desc = query.value(3).toString();
		prov.setDescription(desc);
#ifdef DETAILEDDEBUGGING
		qDebug()<<"  Its description = "<<desc;
#endif
		
		// Get the service URL
		QUrl url(query.value(4).toString());
		prov.setServiceUrl(url);
#ifdef DETAILEDDEBUGGING
		qDebug()<<"  Its url = "<<url.toString();
#endif

		// Get the auth app ID
		QString id(query.value(5).toString());
		prov.setAuthenticationAppId(id);
#ifdef DETAILEDDEBUGGING
		qDebug()<<"  Its auth app id = "<<id;
#endif
		
		// Get the auth app name
		QString name (query.value(6).toString());
		prov.setAuthenticationAppName(name);
#ifdef DETAILEDDEBUGGING
		qDebug()<<"  Its auth app name = "<<name;
#endif

		aMap.insert(pluginId, prov);
		}
	
	if(0 != query.lastError().text().size())
		qDebug()<<"Data base query->next() exited, error = "<<query.lastError().text();
	else
		qDebug()<<"Data base query->next() exited";
	
	qDebug()<<"Count of SmfProvider returned = "<<aMap.count();
	
	// Close the database
	m_pluginDataBase.close();
	}


/**
 * Method to get the pluginID for the mentioned interface and service provider 
 * @param aInterface The interface implemented by the plugin
 * @param aProv The plugin's service provider
 * @param aPluginId The required pluginID. This argument will be empty if no plugin
 * for the given interface and service provider could be found.
 */
void SmfPluginManager::getPluginId(const QString& aInterface, const SmfProvider& aProv, QString& aPluginId)
	{
	qDebug()<<"SmfPluginManager::getPluginId()";
	aPluginId.clear();
	
	if(aInterface.isEmpty())
		{
		qDebug()<<"Interface name is empty!!!";
		return;
		}
	
	// Open the database
	bool opened = m_pluginDataBase.open();
	if(!opened)
		{
		qDebug()<<"Data base not opened, exiting!!!";
		return;
		}
	
#ifdef DETAILEDDEBUGGING
	qDebug()<<"Data base opened";
#endif

	// Query the database for a pluginID with given interface name and service provider
	QSqlQuery query(QString("SELECT pluginId FROM pluginDetails where interfaceName = '%1' AND "
			"serviceProvider = '%2'").arg(aInterface).arg(aProv.serviceName()));
	
	if (query.next())
		{
#ifdef DETAILEDDEBUGGING
		qDebug()<<"Query is success";
#endif
		
		// get the pluginId
		aPluginId = query.value(0).toString();
		qDebug()<<"returned pluginID = "<<aPluginId;
		}
	else
		{		
		if(0 != query.lastError().text().size())
			qDebug()<<"Data base query->next() returned false, error = "<<query.lastError().text();
		else
			qDebug()<<"Data base query->next() returned false";
		}
	
	// Close the database
	m_pluginDataBase.close();
	}