Selaa lähdekoodia

ENH: PluginFramework: Integrated the Qt Mobility service framework

The service framework from Qt Mobility can now be used to register
services and retrieve them in the same way as other PluginFramework
services (using PluginContext::getService).

The service xml file must be named servicedescriptor.xml and added
as a cached resource to the CMake ctkMacroGeneratePlugin macro. The
name of the service must be of the following form:

<plugin-symbolicname>_<version>

For example: org.commontk.myplugin_0.2.1

Additionally, the service xml file has to contain a custom property
with the key "objectclass" and the value being the class name of
the interface.
Sascha Zelzer 15 vuotta sitten
vanhempi
commit
866b20963a

+ 12 - 0
Applications/ctkPluginBrowser/ctkPluginBrowser.cxx

@@ -48,6 +48,12 @@ namespace ctk {
     QStringList pluginDirs;
     pluginDirs << qApp->applicationDirPath() + "/Plugins";
 
+    QStringListIterator dirIt(pluginDirs);
+    while (dirIt.hasNext())
+    {
+      QApplication::addLibraryPath(dirIt.next());
+    }
+
     QDirIterator dirIter(pluginDirs.at(0), QDir::Files);
     while(dirIter.hasNext())
     {
@@ -110,6 +116,12 @@ namespace ctk {
       qDebug() << "Service from" << ref->getPlugin()->getSymbolicName() << ":" << ref->getPropertyKeys();
       qDebug() << "Object Classes:" << ref->getProperty(PluginConstants::OBJECTCLASS).toStringList();
     }
+
+    ServiceReference* cliRef = plugin->getPluginContext()->getServiceReference("ctk::ICLIManager");
+    QObject* cliService = plugin->getPluginContext()->getService(cliRef);
+    if (cliService)
+      qDebug() << "Got service object: " << cliService->metaObject()->className();
+    else qDebug() << "Got null service";
   }
 
   void PluginBrowser::qtResourceDoubleClicked(const QModelIndex& index)

+ 2 - 0
Libs/PluginFramework/CMakeLists.txt

@@ -61,6 +61,8 @@ SET(KIT_SRCS
   ctkPluginManifest.cxx
   ctkPluginPrivate.cxx
   ctkPlugins.cxx
+  ctkQtServiceRegistration.cxx
+  ctkQtServiceRegistrationPrivate.cxx
   ctkRequirePlugin.cxx
   ctkServiceException.cxx
   ctkServiceReference.cxx

+ 15 - 4
Libs/PluginFramework/ctkPlugin.cxx

@@ -84,12 +84,19 @@ namespace ctk {
     //4: Resolve plugin (if needed)
     d->getUpdatedState();
 
-    //5: Eager?
-    if ((options & START_ACTIVATION_POLICY) && d->eagerActivation )
+    //5: Register Qt Mobility service xml files
+    //only register if we are not already in the STARTING state
+    if (d->state != STARTING)
     {
-      d->finalizeActivation();
+      QByteArray serviceDescriptor = getResource("servicedescriptor.xml");
+      if (!serviceDescriptor.isEmpty())
+      {
+        d->fwCtx->services.registerService(d, serviceDescriptor);
+      }
     }
-    else
+
+    //6: Eager?
+    if ((options & START_ACTIVATION_POLICY) && !d->eagerActivation )
     {
       if (STARTING == d->state) return;
       d->state = STARTING;
@@ -97,6 +104,10 @@ namespace ctk {
       PluginEvent pluginEvent(PluginEvent::LAZY_ACTIVATION, this);
       d->fwCtx->listeners.emitPluginChanged(pluginEvent);
     }
+    else
+    {
+      d->finalizeActivation();
+    }
   }
 
   void Plugin::stop(const StopOptions& options)

+ 1 - 1
Libs/PluginFramework/ctkPlugin.h

@@ -350,7 +350,7 @@ namespace ctk {
      * @throws std::logic_error If this plugin has been uninstalled or this
      *         plugin tries to change its own state.
      */
-    virtual void start(const StartOptions& options = 0);
+    virtual void start(const StartOptions& options = START_ACTIVATION_POLICY);
 
     /**
      * Stops this plugin.

+ 50 - 7
Libs/PluginFramework/ctkPluginDatabase.cxx

@@ -22,13 +22,16 @@
 #include "ctkPluginDatabase_p.h"
 #include "ctkPluginDatabaseException.h"
 #include "ctkPlugin.h"
+#include "ctkPluginConstants.h"
 #include "ctkPluginException.h"
 #include "ctkPluginArchive_p.h"
 #include "ctkPluginStorage_p.h"
+#include "ctkServiceException.h"
 
 #include <QApplication>
 #include <QFileInfo>
 #include <QUrl>
+#include <QServiceManager>
 
 #include <QDebug>
 
@@ -181,12 +184,13 @@ void PluginDatabase::updateDB()
 
   beginTransaction(&query, Write);
 
-  QString statement = "SELECT ID, Location, LocalPath, Timestamp FROM Plugins WHERE State != ?";
+  QString statement = "SELECT ID, Location, LocalPath, Timestamp, SymbolicName, Version FROM Plugins WHERE State != ?";
   QList<QVariant> bindValues;
   bindValues.append(Plugin::UNINSTALLED);
 
   QList<qlonglong> outdatedIds;
   QList<QPair<QString,QString> > outdatedPlugins;
+  QStringList outdatedServiceNames;
   try
   {
     executeQuery(&query, statement, bindValues);
@@ -198,6 +202,7 @@ void PluginDatabase::updateDB()
       {
         outdatedIds.append(query.value(EBindIndex).toLongLong());
         outdatedPlugins.append(qMakePair(query.value(EBindIndex1).toString(), query.value(EBindIndex2).toString()));
+        outdatedServiceNames.append(query.value(EBindIndex4).toString() + "_" + query.value(EBindIndex5).toString());
       }
     }
   }
@@ -227,6 +232,29 @@ void PluginDatabase::updateDB()
     throw;
   }
 
+  try
+  {
+    QtMobility::QServiceManager serviceManager;
+    QStringListIterator serviceNameIter(outdatedServiceNames);
+    while (serviceNameIter.hasNext())
+    {
+      QString serviceName = serviceNameIter.next();
+      serviceManager.removeService(serviceName);
+      QtMobility::QServiceManager::Error error = serviceManager.error();
+      if (!(error == QtMobility::QServiceManager::NoError ||
+            error == QtMobility::QServiceManager::ComponentNotFound))
+      {
+        throw ServiceException(QString("Removing service named ") + serviceName +
+                               " failed: " + QString::number(serviceManager.error()));
+      }
+    }
+  }
+  catch (...)
+  {
+    rollbackTransaction(&query);
+    throw;
+  }
+
   commitTransaction(&query);
 
   QListIterator<QPair<QString,QString> > locationIter(outdatedPlugins);
@@ -260,15 +288,17 @@ PluginArchive* PluginDatabase::insertPlugin(const QUrl& location, const QString&
 
   beginTransaction(&query, Write);
 
-  QString statement = "INSERT INTO Plugins(Location,LocalPath,State,Timestamp) VALUES(?,?,?,?)";
+  QString statement = "INSERT INTO Plugins(Location,LocalPath,SymbolicName,Version,State,Timestamp) VALUES(?,?,?,?,?,?)";
 
   QList<QVariant> bindValues;
   bindValues.append(location.toString());
   bindValues.append(localPath);
+  bindValues.append(QString("na"));
+  bindValues.append(QString("na"));
   bindValues.append(Plugin::INSTALLED);
   bindValues.append(lastModified);
 
-  long pluginId = -1;
+  qlonglong pluginId = -1;
   try
   {
     executeQuery(&query, statement, bindValues);
@@ -325,13 +355,24 @@ PluginArchive* PluginDatabase::insertPlugin(const QUrl& location, const QString&
 
   try
   {
-    PluginArchive* archive = 0;
-    if (createArchive)
+    PluginArchive* archive = new PluginArchive(m_PluginStorage, location, localPath,
+                                               pluginId);;
+
+    statement = "UPDATE Plugins SET SymbolicName=?,Version=? WHERE ID=?";
+    QString versionString = archive->getAttribute(PluginConstants::PLUGIN_VERSION);
+    bindValues.clear();
+    bindValues.append(archive->getAttribute(PluginConstants::PLUGIN_SYMBOLICNAME));
+    bindValues.append(versionString.isEmpty() ? "0.0.0" : versionString);
+    bindValues.append(pluginId);
+
+    if (!createArchive)
     {
-      archive = new PluginArchive(m_PluginStorage, location, localPath,
-                                  pluginId);
+      delete archive;
+      archive = 0;
     }
 
+    executeQuery(&query, statement, bindValues);
+
     commitTransaction(&query);
 
     return archive;
@@ -548,6 +589,8 @@ void PluginDatabase::createTables()
                       "ID INTEGER PRIMARY KEY,"
                       "Location TEXT NOT NULL UNIQUE,"
                       "LocalPath TEXT NOT NULL UNIQUE,"
+                      "SymbolicName TEXT NOT NULL,"
+                      "Version TEXT NOT NULL,"
                       "State INTEGER NOT NULL,"
                       "Timestamp TEXT NOT NULL)");
     try

+ 38 - 0
Libs/PluginFramework/ctkQtServiceRegistration.cxx

@@ -0,0 +1,38 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+#include "ctkQtServiceRegistration_p.h"
+#include "ctkQtServiceRegistrationPrivate.h"
+
+#include <QServiceInterfaceDescriptor>
+
+namespace ctk {
+
+  QtServiceRegistration::QtServiceRegistration(PluginPrivate* plugin,
+                                               QtMobility::QServiceInterfaceDescriptor serviceDescriptor,
+                                               const ServiceProperties& props)
+    : ServiceRegistration(*new QtServiceRegistrationPrivate(this, plugin, serviceDescriptor, props))
+  {
+
+  }
+
+}
+

+ 50 - 0
Libs/PluginFramework/ctkQtServiceRegistrationPrivate.cxx

@@ -0,0 +1,50 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+#include "ctkQtServiceRegistrationPrivate.h"
+
+#include "ctkPluginPrivate_p.h"
+#include "ctkPluginFrameworkContext_p.h"
+#include "ctkQtServiceRegistration_p.h"
+
+namespace ctk {
+
+  QtServiceRegistrationPrivate::QtServiceRegistrationPrivate(QtServiceRegistration* sr,
+                               PluginPrivate* plugin,
+                               QtMobility::QServiceInterfaceDescriptor serviceDescriptor,
+                               const ServiceProperties& props)
+    : ServiceRegistrationPrivate(sr, plugin, 0, props),
+      serviceDescriptor(serviceDescriptor)
+  {
+
+  }
+
+  QObject* QtServiceRegistrationPrivate::getService()
+  {
+    if (this->plugin->state != Plugin::ACTIVE)
+    {
+      this->plugin->q_func()->start(0);
+    }
+    return this->plugin->fwCtx->services.qServiceManager.loadInterface(serviceDescriptor);
+  }
+
+}
+

+ 53 - 0
Libs/PluginFramework/ctkQtServiceRegistrationPrivate.h

@@ -0,0 +1,53 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#ifndef CTKQTSERVICEREGISTRATIONPRIVATE_H
+#define CTKQTSERVICEREGISTRATIONPRIVATE_H
+
+#include "ctkServiceRegistrationPrivate.h"
+
+#include "QServiceInterfaceDescriptor"
+
+namespace ctk {
+
+  class QtServiceRegistration;
+
+  class QtServiceRegistrationPrivate : public ServiceRegistrationPrivate
+  {
+  public:
+
+    QtServiceRegistrationPrivate(QtServiceRegistration* sr,
+                                 PluginPrivate* plugin,
+                                 QtMobility::QServiceInterfaceDescriptor serviceDescriptor,
+                                 const ServiceProperties& props);
+
+    QObject* getService();
+
+  protected:
+
+    QtMobility::QServiceInterfaceDescriptor serviceDescriptor;
+
+  };
+
+}
+
+#endif // CTKQTSERVICEREGISTRATIONPRIVATE_H

+ 46 - 0
Libs/PluginFramework/ctkQtServiceRegistration_p.h

@@ -0,0 +1,46 @@
+/*=============================================================================
+
+  Library: CTK
+
+  Copyright (c) 2010 German Cancer Research Center,
+    Division of Medical and Biological Informatics
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+=============================================================================*/
+
+
+#ifndef CTKQTSERVICEREGISTRATION_P_H
+#define CTKQTSERVICEREGISTRATION_P_H
+
+#include "ctkServiceRegistration.h"
+
+#include <QServiceInterfaceDescriptor>
+
+namespace ctk {
+
+  class PluginPrivate;
+
+  class QtServiceRegistration : public ServiceRegistration
+  {
+
+  public:
+
+    QtServiceRegistration(PluginPrivate* plugin,
+                          QtMobility::QServiceInterfaceDescriptor serviceDescriptor,
+                          const ServiceProperties& props);
+  };
+
+}
+
+#endif // CTKQTSERVICEREGISTRATION_P_H

+ 5 - 5
Libs/PluginFramework/ctkServiceReferencePrivate.cxx

@@ -51,7 +51,7 @@ namespace ctk {
           QStringList classes =
               registration->properties.value(PluginConstants::OBJECTCLASS).toStringList();
           registration->dependents[plugin] = 1;
-          if (ServiceFactory* serviceFactory = qobject_cast<ServiceFactory*>(registration->service))
+          if (ServiceFactory* serviceFactory = qobject_cast<ServiceFactory*>(registration->getService()))
           {
             try
             {
@@ -89,19 +89,19 @@ namespace ctk {
           }
           else
           {
-            s = registration->service;
+            s = registration->getService();
           }
         }
         else
         {
           registration->dependents.insert(plugin, count + 1);
-          if (qobject_cast<ServiceFactory*>(registration->service))
+          if (qobject_cast<ServiceFactory*>(registration->getService()))
           {
             s = registration->serviceInstances.value(plugin);
           }
           else
           {
-            s = registration->service;
+            s = registration->getService();
           }
         }
       }
@@ -157,7 +157,7 @@ namespace ctk {
         {
           try
           {
-            qobject_cast<ServiceFactory*>(registration->service)->ungetService(plugin,
+            qobject_cast<ServiceFactory*>(registration->getService())->ungetService(plugin,
                 registration->q_func(), sfi);
           }
           catch (const std::exception& e)

+ 6 - 0
Libs/PluginFramework/ctkServiceRegistration.cxx

@@ -38,6 +38,12 @@ namespace ctk {
 
   }
 
+  ServiceRegistration::ServiceRegistration(ServiceRegistrationPrivate& dd)
+    : d_ptr(&dd)
+  {
+
+  }
+
   ServiceReference* ServiceRegistration::getReference()
   {
     Q_D(ServiceRegistration);

+ 4 - 2
Libs/PluginFramework/ctkServiceRegistration.h

@@ -125,17 +125,19 @@ namespace ctk {
      * @see BundleContext#ungetService
      * @see ServiceFactory#ungetService
      */
-    void unregister();
+    virtual void unregister();
 
     bool operator<(const ServiceRegistration& o) const;
 
-  private:
+  protected:
 
     friend class Services;
 
     ServiceRegistration(PluginPrivate* plugin, QObject* service,
                         const ServiceProperties& props);
 
+    ServiceRegistration(ServiceRegistrationPrivate& dd);
+
     ServiceRegistrationPrivate * const d_ptr;
 
   };

+ 5 - 0
Libs/PluginFramework/ctkServiceRegistrationPrivate.cxx

@@ -43,5 +43,10 @@ namespace ctk {
     return deps.contains(p);
   }
 
+  QObject* ServiceRegistrationPrivate::getService()
+  {
+    return service;
+  }
+
 }
 

+ 8 - 6
Libs/PluginFramework/ctkServiceRegistrationPrivate.h

@@ -40,6 +40,11 @@ namespace ctk {
 
     ServiceRegistration* const q_ptr;
 
+    /**
+     * Service or ServiceFactory object.
+     */
+    QObject* service;
+
   public:
 
     Q_DECLARE_PUBLIC(ServiceRegistration);
@@ -51,11 +56,6 @@ namespace ctk {
     PluginPrivate* plugin;
 
     /**
-     * Service or ServiceFactory object.
-     */
-    QObject* service;
-
-    /**
      * Reference object to this service registration.
      */
     ServiceReference* reference;
@@ -99,7 +99,7 @@ namespace ctk {
     ServiceRegistrationPrivate(ServiceRegistration* sr, PluginPrivate* plugin, QObject* service,
                                const ServiceProperties& props);
 
-    ~ServiceRegistrationPrivate();
+    virtual ~ServiceRegistrationPrivate();
 
     /**
      * Check if a plugin uses this service
@@ -109,6 +109,8 @@ namespace ctk {
      */
     bool isUsedByPlugin(Plugin* p);
 
+    virtual QObject* getService();
+
   };
 
 }

+ 114 - 1
Libs/PluginFramework/ctkServices.cxx

@@ -23,15 +23,19 @@
 
 #include <QStringListIterator>
 #include <QMutexLocker>
+#include <QBuffer>
 
 #include <algorithm>
 
 #include "ctkServiceFactory.h"
 #include "ctkPluginConstants.h"
 #include "ctkServiceRegistrationPrivate.h"
+#include "ctkQtServiceRegistration_p.h"
 
 namespace ctk {
 
+  using namespace QtMobility;
+
   //TODO: this is just a mock class. Wait for the real thing
   class LDAPExpr
   {
@@ -112,7 +116,7 @@ namespace ctk {
 
 
 Services::Services(PluginFrameworkContext* fwCtx)
-  : framework(fwCtx)
+  : mutex(QMutex::Recursive), framework(fwCtx)
 {
 
 }
@@ -184,6 +188,115 @@ ServiceRegistration* Services::registerService(PluginPrivate* plugin,
   return res;
 }
 
+void Services::registerService(PluginPrivate* plugin, QByteArray serviceDescription)
+{
+  QMutexLocker lock(&mutex);
+
+  QBuffer serviceBuffer(&serviceDescription);
+  qServiceManager.addService(&serviceBuffer);
+  QServiceManager::Error error = qServiceManager.error();
+  if (!(error == QServiceManager::NoError || error == QServiceManager::ServiceAlreadyExists))
+  {
+    throw std::invalid_argument(std::string("Registering the service descriptor for plugin ")
+                                + plugin->symbolicName.toStdString() + " failed: " +
+                                getQServiceManagerErrorString(error).toStdString());
+  }
+
+  QString serviceName = plugin->symbolicName + "_" + plugin->version.toString();
+  QList<QServiceInterfaceDescriptor> descriptors = qServiceManager.findInterfaces(serviceName);
+
+  if (descriptors.isEmpty())
+  {
+    qDebug().nospace() << "Warning: No interfaces found for service name " << serviceName
+        << " in plugin " << plugin->symbolicName << " (Version " << plugin->version.toString() << ")";
+  }
+
+  QListIterator<QServiceInterfaceDescriptor> it(descriptors);
+  while (it.hasNext())
+  {
+    QServiceInterfaceDescriptor descr = it.next();
+    qDebug() << "Registering:" << descr.interfaceName();
+    QStringList classes;
+    ServiceProperties props;
+
+    QStringList customKeys = descr.customAttributes();
+    QStringListIterator keyIt(customKeys);
+    bool classAttrFound = false;
+    while (keyIt.hasNext())
+    {
+      QString key = keyIt.next();
+      if (key == PluginConstants::OBJECTCLASS)
+      {
+        classAttrFound = true;
+        classes << descr.customAttribute(key);
+      }
+      else
+      {
+        props.insert(key, descr.customAttribute(key));
+      }
+    }
+
+    if (!classAttrFound)
+    {
+      throw std::invalid_argument(std::string("The custom attribute \"") +
+                                  PluginConstants::OBJECTCLASS.toStdString() +
+                                  "\" is missing in the interface description of \"" +
+                                  descr.interfaceName().toStdString());
+    }
+
+    ServiceRegistration* res = new QtServiceRegistration(plugin,
+                                                         descr,
+                                                         createServiceProperties(props, classes));
+    services.insert(res, classes);
+    for (QStringListIterator i(classes); i.hasNext(); )
+    {
+      QString currClass = i.next();
+      QList<ServiceRegistration*>& s = classServices[currClass];
+      QList<ServiceRegistration*>::iterator ip =
+          std::lower_bound(s.begin(), s.end(), res, ServiceRegistrationComparator());
+      s.insert(ip, res);
+    }
+
+    //ServiceReference* r = res->getReference();
+    // TODO
+    //Listeners l = bundle.fwCtx.listeners;
+    //l.serviceChanged(l.getMatchingServiceListeners(r),
+    //                 new ServiceEvent(ServiceEvent.REGISTERED, r),
+    //                 null);
+  }
+}
+
+QString Services::getQServiceManagerErrorString(QServiceManager::Error error)
+{
+  switch (error)
+  {
+  case QServiceManager::NoError:
+    return QString("No error occurred.");
+  case QServiceManager::StorageAccessError:
+    return QString("The service data storage is not accessible. This could be because the caller does not have the required permissions.");
+  case QServiceManager::InvalidServiceLocation:
+    return QString("The service was not found at its specified location.");
+  case QServiceManager::InvalidServiceXml:
+    return QString("The XML defining the service metadata is invalid.");
+  case QServiceManager::InvalidServiceInterfaceDescriptor:
+    return QString("The service interface descriptor is invalid, or refers to an interface implementation that cannot be accessed in the current scope.");
+  case QServiceManager::ServiceAlreadyExists:
+    return QString("Another service has previously been registered with the same location.");
+  case QServiceManager::ImplementationAlreadyExists:
+    return QString("Another service that implements the same interface version has previously been registered.");
+  case QServiceManager::PluginLoadingFailed:
+    return QString("The service plugin cannot be loaded.");
+  case QServiceManager::ComponentNotFound:
+    return QString("The service or interface implementation has not been registered.");
+  case QServiceManager::ServiceCapabilityDenied:
+    return QString("The security session does not allow the service based on its capabilities.");
+  case QServiceManager::UnknownError:
+    return QString("An unknown error occurred.");
+  default:
+    return QString("Unknown error enum.");
+  }
+}
+
 void Services::updateServiceRegistrationOrder(ServiceRegistration* sr,
                                               const QStringList& classes)
 {

+ 7 - 0
Libs/PluginFramework/ctkServices_p.h

@@ -27,6 +27,7 @@
 #include <QObject>
 #include <QMutex>
 #include <QStringList>
+#include <QServiceManager>
 
 #include "ctkServiceRegistration.h"
 #include "ctkPluginPrivate_p.h"
@@ -43,6 +44,8 @@ public:
 
   mutable QMutex mutex;
 
+  QtMobility::QServiceManager qServiceManager;
+
   /**
    * Creates a new ServiceProperties object containing <code>in</code>
    * with the keys converted to lower case.
@@ -99,6 +102,8 @@ public:
                                QObject* service,
                                const ServiceProperties& properties);
 
+  void registerService(PluginPrivate* plugin, QByteArray serviceDescription);
+
 
   /**
    * Service ranking changed, reorder registered services
@@ -178,6 +183,8 @@ public:
    */
   QList<ServiceRegistration*> getUsedByPlugin(Plugin* p) const;
 
+  QString getQServiceManagerErrorString(QtMobility::QServiceManager::Error error);
+
 };
 
 }

+ 1 - 0
Plugins/org.commontk.cli/CMakeLists.txt

@@ -9,6 +9,7 @@ SET(PLUGIN_SRCS
 SET(PLUGIN_MOC_SRCS
   ctkCLIPlugin.h
   ctkCLIRegistry.h
+  ctkICLIManager.h
 )
 
 SET(PLUGIN_resources

+ 11 - 0
Plugins/org.commontk.cli/ctkICLIManager.h

@@ -8,5 +8,16 @@
 #ifndef CTKICLIMANAGER_H_
 #define CTKICLIMANAGER_H_
 
+#include <QObject>
+
+namespace ctk {
+
+  class ICLIManager : public QObject
+  {
+    Q_OBJECT
+  };
+
+}
+
 
 #endif /* CTKICLIMANAGER_H_ */

+ 1 - 1
Plugins/org.commontk.cli/manifest_headers.cmake

@@ -1 +1 @@
-SET(Plugin-ActivationPolicy eager)
+#SET(Plugin-ActivationPolicy eager)

+ 2 - 1
Plugins/org.commontk.cli/servicedescriptor.xml

@@ -1,11 +1,12 @@
 <?xml version="1.0" encoding="utf-8" ?>
   <service>
-    <name>ctkCLIService</name>
+    <name>org.commontk.cli_0.0.0</name>
     <filepath>liborg_commontk_cli</filepath>
     <interface>
       <name>org.commontk.cli.ICLIManager</name>
       <version>1.0</version>
       <capabilities></capabilities>
+      <customproperty key="objectclass">ctk::ICLIManager</customproperty>
       <description>Interface that allows to discover and manage CLI modules</description>
     </interface>
   </service>