summaryrefslogtreecommitdiff
path: root/src/ivicore/qtiviservicemanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ivicore/qtiviservicemanager.cpp')
-rw-r--r--src/ivicore/qtiviservicemanager.cpp291
1 files changed, 291 insertions, 0 deletions
diff --git a/src/ivicore/qtiviservicemanager.cpp b/src/ivicore/qtiviservicemanager.cpp
new file mode 100644
index 0000000..f7046ca
--- /dev/null
+++ b/src/ivicore/qtiviservicemanager.cpp
@@ -0,0 +1,291 @@
+/************************************************************************************************
+ * Copyright (c) 2012-2015 Pelagicore AG. All rights reserved.
+ *
+ * This software, including documentation, is protected by copyright controlled by Pelagicore AG.
+ * All rights reserved. Copying, including reproducing, storing, adapting or translating, any or
+ * all of this material requires prior written consent of Pelagicore AG Corporation. This material
+ * also contains confidential information which may not be disclosed to others without the prior
+ * written consent of Pelagicore AG.
+ ************************************************************************************************/
+
+#include "qtiviservicemanager.h"
+
+#include "qtiviproxyserviceobject_p.h"
+#include "qtiviservicemanager_p.h"
+
+#include <QStringList>
+#include <QPluginLoader>
+#include <QJsonObject>
+#include <QCoreApplication>
+#include <QDir>
+#include <QModelIndex>
+#include <QDebug>
+
+#define QTIVI_PLUGIN_DIRECTORY "qtivi"
+
+QtIVIServiceManagerPrivate::QtIVIServiceManagerPrivate(QtIVIServiceManager *parent) : QObject(parent), q_ptr(parent)
+{
+}
+
+QList<QtIVIServiceObject *> QtIVIServiceManagerPrivate::findServiceByInterface(const QString &interface)
+{
+ QList<QtIVIServiceObject*> list;
+
+ foreach (Backend *backend, m_backends) {
+
+ if (backend->metaData[QLatin1String("interfaces")].toStringList().contains(interface)) {
+ QtIVIServiceInterface *backendInterface = loadServiceBackendInterface(backend);
+ list.append(new QtIVIProxyServiceObject(backendInterface));
+ }
+ }
+
+ return list;
+}
+
+void QtIVIServiceManagerPrivate::searchPlugins()
+{
+ bool found = false;
+ foreach (const QString &pluginDir, QCoreApplication::libraryPaths()) {
+
+ QDir dir(pluginDir);
+ QString path = pluginDir + QDir::separator() + QLatin1Literal(QTIVI_PLUGIN_DIRECTORY);
+ //Check whether the directory exists
+ if (!QDir(path).exists(QStringLiteral(".")))
+ continue;
+
+ QStringList plugins = QDir(path).entryList(QDir::Files);
+ foreach (const QString &pluginPath, plugins) {
+ QString fileName = QDir::cleanPath(path + QLatin1Char('/') + pluginPath);
+ QPluginLoader loader(dir.absoluteFilePath(fileName));
+ registerBackend(loader.fileName(), loader.metaData());
+ found = true;
+ }
+ }
+ if (!found)
+ {
+ qWarning() << "No plugins found in search path: " << QCoreApplication::libraryPaths().join(QLatin1String(":"));
+ }
+}
+
+void QtIVIServiceManagerPrivate::registerBackend(const QString fileName, const QJsonObject metaData)
+{
+ QVariantMap backendMetaData = metaData.value(QLatin1String("MetaData")).toVariant().toMap();
+
+ if (backendMetaData[QLatin1String("interfaces")].isNull() || backendMetaData[QLatin1String("interfaces")].toList().isEmpty()) {
+ qDebug("PluginManager - Malformed metaData in '%s'. MetaData must contain a list of interfaces", qPrintable(fileName));
+ return;
+ }
+
+ //TODO check for other metaData like name etc.
+
+ backendMetaData.insert(QLatin1String("fileName"), fileName);
+
+ Backend* backend = new Backend;
+ backend->metaData = backendMetaData;
+ backend->interface = 0;
+ backend->interfaceObject = 0;
+ backend->loader = 0;
+ addBackend(backend);
+}
+
+bool QtIVIServiceManagerPrivate::registerBackend(QObject *serviceBackendInterface, const QStringList &interfaces)
+{
+ if (interfaces.isEmpty()) {
+ return false;
+ }
+
+ // Verify that the object implements the ServiceBackendInterface
+ QtIVIServiceInterface *interface = qobject_cast<QtIVIServiceInterface*>(serviceBackendInterface);
+ if (!interface) {
+ return false;
+ }
+
+ QVariantMap metaData = QVariantMap();
+
+ metaData.insert(QLatin1String("interfaces"), interfaces);
+
+ Backend *backend = new Backend;
+ backend->metaData = metaData;
+ backend->interface = interface;
+ backend->interfaceObject = serviceBackendInterface;
+ backend->loader = 0;
+
+ addBackend(backend);
+ return true;
+}
+
+void QtIVIServiceManagerPrivate::unloadAllBackends()
+{
+ Q_Q(QtIVIServiceManager);
+
+ q->beginResetModel();
+ for(int i=0; i<m_backends.count(); i++) {
+ Backend* backend = m_backends.takeAt(i);
+
+ //If the Interface is from a Plugin, the Plugin owns it and it will be deleted when unloading.
+ //Otherwise we own the Interface and delete the Pointer.
+ if (backend->loader) {
+ backend->loader->unload();
+ delete backend->loader;
+ } else if (backend->interfaceObject) {
+ delete backend->interfaceObject;
+ }
+
+ delete backend;
+ }
+ m_backends.clear();
+ q->endResetModel();
+}
+
+void QtIVIServiceManagerPrivate::addBackend(Backend *backend)
+{
+ Q_Q(QtIVIServiceManager);
+
+ q->beginInsertRows(QModelIndex(), m_backends.count(), m_backends.count());
+ m_backends.append(backend);
+ q->endInsertRows();
+
+ foreach (const QString &interface, backend->metaData[QLatin1String("interfaces")].toStringList()) {
+ m_interfaceNames.insert(interface);
+ }
+}
+
+QtIVIServiceInterface *QtIVIServiceManagerPrivate::loadServiceBackendInterface(struct Backend *backend)
+{
+ if (backend->interface) {
+ return backend->interface;
+ }
+
+ QPluginLoader *loader = new QPluginLoader(backend->metaData[QLatin1String("fileName")].toString());
+ QObject *plugin = loader->instance();
+ if (plugin) {
+
+ QtIVIServiceInterface *backendInterface = qobject_cast<QtIVIServiceInterface*>(plugin);
+ if (backendInterface) {
+ backend->interface = backendInterface;
+ backend->loader = loader;
+ return backend->interface;
+ } else {
+ qDebug("ServiceManager::serviceObjects - failed to cast to interface from '%s'", qPrintable(loader->fileName()));
+ }
+
+ } else {
+ qDebug("ServiceManager::serviceObjects - failed to load '%s'", qPrintable(loader->fileName()));
+ }
+
+ //Only delete the Loader right away if we didn't succeeded with loading the interfaces.
+ delete loader;
+
+ return 0;
+}
+
+/*!
+ * \class QtIVIServiceManager
+ * \brief QtIVIServiceManager provides the Backends to QtIVIAbstractFeature
+ *
+ * QtIVIServiceManager is the heart of QtIVI and provides you a easy way to detect what
+ * Backends and interfaces are available.
+ *
+ * By default QtIVIServiceManager reads the metaData of all plugins within the "qtivi" folder
+ * of your plugin path. The plugin itself will be loaded once it's explictly requested by
+ * the developer by using findServiceByInterface()
+ *
+ * The registerService() function can be used to add Backend classes without putting them into
+ * a plugin.
+ */
+QtIVIServiceManager::QtIVIServiceManager()
+ : QAbstractListModel(0)
+ , d_ptr(new QtIVIServiceManagerPrivate(this))
+{
+ d_ptr->searchPlugins();
+}
+
+QtIVIServiceManager *QtIVIServiceManager::instance()
+{
+ static QtIVIServiceManager* instance = new QtIVIServiceManager();
+ return instance;
+}
+
+QtIVIServiceManager::~QtIVIServiceManager()
+{
+
+}
+
+/*!
+ * Returns a List of Backends which implementing the specified \a interface.
+ */
+QList<QtIVIServiceObject *> QtIVIServiceManager::findServiceByInterface(const QString &interface)
+{
+ Q_D(QtIVIServiceManager);
+ return d->findServiceByInterface(interface);
+}
+
+/*!
+ * Register a backend. The provided \a serviceBackendInterface must implement the ServiceBackendInterface else
+ * the registration will fail.
+ *
+ * \param serviceBackendInterface an QObject instance which implements the ServiceBackendInterface
+ * \param interfaces a list with interfaces which the backend handles. At least one interface is required
+ * \return true if the backend was successfully registered else false
+ * \sa ServiceBackendInterface
+ */
+bool QtIVIServiceManager::registerService(QObject *serviceBackendInterface, const QStringList &interfaces)
+{
+ Q_D(QtIVIServiceManager);
+ return d->registerBackend(serviceBackendInterface, interfaces);
+}
+
+void QtIVIServiceManager::unloadAllBackends()
+{
+ Q_D(QtIVIServiceManager);
+ return d->unloadAllBackends();
+}
+
+/*!
+ * Returns true if the specified \a interface has been registered.
+
+ * \param interface the interface
+ * \return true if the specified \a interface has been registered else false
+ */
+bool QtIVIServiceManager::hasInterface(const QString &interface) const
+{
+ Q_D(const QtIVIServiceManager);
+ return d->m_interfaceNames.contains(interface);
+}
+
+/*!
+ * Implements QAbstractListModel::rowCount()
+ *
+ * \param parent the model index, typically an empty model index
+ * \return the number of interfaces available
+ * \sa QAbstractListModel::data()
+ */
+int QtIVIServiceManager::rowCount(const QModelIndex &parent) const
+{
+ Q_D(const QtIVIServiceManager);
+ return parent.isValid() ? 0 : d->m_backends.count();
+}
+
+/*!
+ * Implements QAbstractListModel::data()
+ *
+ * \param index the index
+ * \param role the role
+ * \return the data for the spcified index and role
+ * \sa QAbstractListModel::data()
+ */
+QVariant QtIVIServiceManager::data(const QModelIndex &index, int role) const
+{
+ Q_D(const QtIVIServiceManager);
+
+ if (!index.isValid())
+ return QVariant();
+
+ int row = index.row();
+
+ if (row >= 0 && row < d->m_backends.count() && role == Qt::DisplayRole) {
+ return QVariant::fromValue<QtIVIServiceInterface*>(d->m_backends.at(index.row())->interface);
+ }
+
+ return QVariant();
+}