Просмотр исходного кода

Implemented service event notifications.

Sascha Zelzer лет назад: 14
Родитель
Сommit
c3b499d879

+ 26 - 0
Libs/PluginFramework/ctkServiceReference.cpp

@@ -46,6 +46,11 @@ ctkServiceReference::~ctkServiceReference()
     delete d_ptr;
 }
 
+bool ctkServiceReference::isNull() const
+{
+  return d_func()->registration == 0;
+}
+
 QVariant ctkServiceReference::getProperty(const QString& key) const
 {
   Q_D(const ctkServiceReference);
@@ -123,3 +128,24 @@ ctkServiceReference& ctkServiceReference::operator=(const ctkServiceReference& r
 
   return *this;
 }
+
+uint qHash(const ctkServiceReference& serviceRef)
+{
+  return qHash(serviceRef.getProperty(ctkPluginConstants::SERVICE_ID).toLongLong());
+}
+
+QDebug operator<<(QDebug dbg, const ctkServiceReference& serviceRef)
+{
+  dbg.nospace() << "Reference for service object registered from "
+      << serviceRef.getPlugin()->getSymbolicName() << " " << serviceRef.getPlugin()->getVersion()
+      << " (";
+  int i = serviceRef.getPropertyKeys().size();
+  foreach(QString key, serviceRef.getPropertyKeys())
+  {
+    dbg.nospace() << key << "=" << serviceRef.getProperty(key).toString();
+    if (--i > 0) dbg.nospace() << ",";
+  }
+  dbg.nospace() << ")";
+
+  return dbg.maybeSpace();
+}

+ 12 - 0
Libs/PluginFramework/ctkServiceReference.h

@@ -31,6 +31,8 @@
 
   class ctkServiceRegistrationPrivate;
   class ctkServiceReferencePrivate;
+  class ctkServiceEvent;
+  template<class Item, class Related> class ctkPluginAbstractTracked;
 
   /**
    * A reference to a service.
@@ -173,15 +175,25 @@
 
   protected:
 
+    friend class ctkLDAPSearchFilter;
     friend class ctkServiceRegistrationPrivate;
     friend class ctkPluginContext;
     friend class ctkPluginPrivate;
+    friend class ctkPluginFrameworkListeners;
+    friend class ctkServiceTrackerPrivate;
+    friend class ctkServiceTracker;
+    friend class ctkPluginAbstractTracked<ctkServiceReference, ctkServiceEvent>;
 
     ctkServiceReference(ctkServiceRegistrationPrivate* reg);
 
+    bool isNull() const;
+
     ctkServiceReferencePrivate * d_ptr;
 
   };
 
+uint CTK_PLUGINFW_EXPORT qHash(const ctkServiceReference& serviceRef);
+QDebug CTK_PLUGINFW_EXPORT operator<<(QDebug dbg, const ctkServiceReference& serviceRef);
+
 
 #endif // CTKSERVICEREFERENCE_H

+ 94 - 102
Libs/PluginFramework/ctkServiceReferencePrivate.cpp

@@ -32,141 +32,133 @@
 #include "ctkPluginFrameworkContext_p.h"
 
 
-  ctkServiceReferencePrivate::ctkServiceReferencePrivate(ctkServiceRegistrationPrivate* reg)
-    : ref(1), registration(reg)
+ctkServiceReferencePrivate::ctkServiceReferencePrivate(ctkServiceRegistrationPrivate* reg)
+  : ref(1), registration(reg)
+{
+}
+
+QObject* ctkServiceReferencePrivate::getService(ctkPlugin* plugin)
+{
+  QObject* s = 0;
   {
-  }
-
-  QObject* ctkServiceReferencePrivate::getService(ctkPlugin* plugin)
-  {
-    QObject* s = 0;
+    QMutexLocker lock(&registration->propsLock);
+    if (registration->available)
     {
-      QMutexLocker lock(&registration->propsLock);
-      if (registration->available)
+      int count = registration->dependents.value(plugin);
+      if (count == 0)
       {
-        int count = registration->dependents.value(plugin);
-        if (count == 0)
+        QStringList classes =
+            registration->properties.value(ctkPluginConstants::OBJECTCLASS).toStringList();
+        registration->dependents[plugin] = 1;
+        if (ctkServiceFactory* serviceFactory = qobject_cast<ctkServiceFactory*>(registration->getService()))
         {
-          QStringList classes =
-              registration->properties.value(ctkPluginConstants::OBJECTCLASS).toStringList();
-          registration->dependents[plugin] = 1;
-          if (ctkServiceFactory* serviceFactory = qobject_cast<ctkServiceFactory*>(registration->getService()))
+          try
           {
-            try
-            {
-              s = serviceFactory->getService(plugin, registration->q_func());
-            }
-            catch (const std::exception& pe)
-            {
-              ctkServiceException se("ctkServiceFactory throw an exception",
-                                  ctkServiceException::FACTORY_EXCEPTION, pe);
-              plugin->d_func()->fwCtx->listeners.frameworkError
+            s = serviceFactory->getService(plugin, registration->q_func());
+          }
+          catch (const std::exception& pe)
+          {
+            ctkServiceException se("ctkServiceFactory throw an exception",
+                                   ctkServiceException::FACTORY_EXCEPTION, pe);
+            plugin->d_func()->fwCtx->listeners.frameworkError
                 (registration->plugin->q_func(), se);
-              return 0;
-            }
-            if (s == 0) {
-              ctkServiceException se("ctkServiceFactory produced null",
-                                  ctkServiceException::FACTORY_ERROR);
-              plugin->d_func()->fwCtx->listeners.frameworkError
+            return 0;
+          }
+          if (s == 0) {
+            ctkServiceException se("ctkServiceFactory produced null",
+                                   ctkServiceException::FACTORY_ERROR);
+            plugin->d_func()->fwCtx->listeners.frameworkError
                 (registration->plugin->q_func(), se);
-              return 0;
-            }
-            for (QStringListIterator i(classes); i.hasNext(); )
+            return 0;
+          }
+          for (QStringListIterator i(classes); i.hasNext(); )
+          {
+            QString cls = i.next();
+            if (!registration->plugin->fwCtx->services.checkServiceClass(s, cls))
             {
-              QString cls = i.next();
-              if (!registration->plugin->fwCtx->services.checkServiceClass(s, cls))
-              {
-                ctkServiceException se(QString("ctkServiceFactory produced an object ") +
+              ctkServiceException se(QString("ctkServiceFactory produced an object ") +
                                      "that did not implement: " + cls,
                                      ctkServiceException::FACTORY_ERROR);
-                plugin->d_func()->fwCtx->listeners.frameworkError
+              plugin->d_func()->fwCtx->listeners.frameworkError
                   (registration->plugin->q_func(), se);
-                return 0;
-              }
+              return 0;
             }
-            registration->serviceInstances.insert(plugin, s);
-          }
-          else
-          {
-            s = registration->getService();
           }
+          registration->serviceInstances.insert(plugin, s);
         }
         else
         {
-          registration->dependents.insert(plugin, count + 1);
-          if (qobject_cast<ctkServiceFactory*>(registration->getService()))
-          {
-            s = registration->serviceInstances.value(plugin);
-          }
-          else
-          {
-            s = registration->getService();
-          }
+          s = registration->getService();
+        }
+      }
+      else
+      {
+        registration->dependents.insert(plugin, count + 1);
+        if (qobject_cast<ctkServiceFactory*>(registration->getService()))
+        {
+          s = registration->serviceInstances.value(plugin);
+        }
+        else
+        {
+          s = registration->getService();
         }
       }
     }
-    return s;
   }
+  return s;
+}
 
-  /**
-     * Unget the service object.
-     *
-     * @param bundle Bundle who wants remove service.
-     * @param checkRefCounter If true decrement refence counter and remove service
-     *                        if we reach zero. If false remove service without
-     *                        checking refence counter.
-     * @return True if service was remove or false if only refence counter was
-     *         decremented.
-     */
-  bool ctkServiceReferencePrivate::ungetService(ctkPlugin* plugin, bool checkRefCounter)
-  {
-    QMutexLocker lock(&registration->propsLock);
-    bool hadReferences = false;
-    bool removeService = false;
+bool ctkServiceReferencePrivate::ungetService(ctkPlugin* plugin, bool checkRefCounter)
+{
+  QMutexLocker lock(&registration->propsLock);
+  bool hadReferences = false;
+  bool removeService = false;
 
-    int count= registration->dependents.value(plugin);
-    if (count > 0)
-    {
-      hadReferences = true;
-    }
+  int count= registration->dependents.value(plugin);
+  if (count > 0)
+  {
+    hadReferences = true;
+  }
 
-    if(checkRefCounter)
+  if(checkRefCounter)
+  {
+    if (count > 1)
     {
-      if (count > 1)
-      {
-          registration->dependents[plugin] = count - 1;
-      }
-      else if(count == 1)
-      {
-        removeService = true;
-      }
+      registration->dependents[plugin] = count - 1;
     }
-    else
+    else if(count == 1)
     {
       removeService = true;
     }
+  }
+  else
+  {
+    removeService = true;
+  }
 
-    if (removeService)
+  if (removeService)
+  {
+    QObject* sfi = registration->serviceInstances[plugin];
+    registration->serviceInstances.remove(plugin);
+    if (sfi != 0)
     {
-      QObject* sfi = registration->serviceInstances[plugin];
-      registration->serviceInstances.remove(plugin);
-      if (sfi != 0)
+      try
       {
-        try
-        {
-          qobject_cast<ctkServiceFactory*>(registration->getService())->ungetService(plugin,
-              registration->q_func(), sfi);
-        }
-        catch (const std::exception& e)
-        {
-          plugin->d_func()->fwCtx->listeners.frameworkError(registration->plugin->q_func(), e);
-        }
+        qobject_cast<ctkServiceFactory*>(registration->getService())->ungetService(plugin,
+                                                                                   registration->q_func(), sfi);
+      }
+      catch (const std::exception& e)
+      {
+        plugin->d_func()->fwCtx->listeners.frameworkError(registration->plugin->q_func(), e);
       }
-      registration->dependents.remove(plugin);
     }
-
-    return hadReferences;
+    registration->dependents.remove(plugin);
   }
 
+  return hadReferences;
+}
 
-
+ServiceProperties ctkServiceReferencePrivate::getProperties() const
+{
+  return registration->properties;
+}

+ 10 - 0
Libs/PluginFramework/ctkServiceReferencePrivate.h

@@ -25,6 +25,8 @@
 
 #include <QAtomicInt>
 
+#include "ctkPluginFramework_global.h"
+
 class QObject;
 
 class ctkServiceRegistrationPrivate;
@@ -59,6 +61,14 @@ public:
   bool ungetService(ctkPlugin* plugin, bool checkRefCounter);
 
   /**
+   * Get all properties registered with this service.
+   *
+   * @return A ServiceProperties object containing properties or being empty
+   *         if service has been removed.
+   */
+  ServiceProperties getProperties() const;
+
+  /**
    * Reference count for implicitly shared private implementation.
    */
   QAtomicInt ref;

+ 40 - 38
Libs/PluginFramework/ctkServiceRegistration.cpp

@@ -23,7 +23,9 @@
 #include "ctkServiceRegistrationPrivate.h"
 #include "ctkPluginFrameworkContext_p.h"
 #include "ctkPluginPrivate_p.h"
+#include "ctkPluginConstants.h"
 #include "ctkServiceFactory.h"
+#include "ctkServiceSlotEntry_p.h"
 
 #include <QMutex>
 
@@ -52,41 +54,43 @@ ctkServiceReference ctkServiceRegistration::getReference() const
   return d->reference;
 }
 
-void ctkServiceRegistration::setProperties(const ServiceProperties& properties)
+void ctkServiceRegistration::setProperties(const ServiceProperties& props)
 {
-  Q_UNUSED(properties)
-//    QMutexLocker lock(eventLock);
-//          Set before;
-//          // TBD, optimize the locking of services
-//          synchronized (bundle.fwCtx.services) {
-//
-//            synchronized (properties) {
-//              if (available) {
-//                // NYI! Optimize the MODIFIED_ENDMATCH code
-//                Object old_rank = properties.get(Constants.SERVICE_RANKING);
-//                before = bundle.fwCtx.listeners.getMatchingServiceListeners(reference);
-//                String[] classes = (String[])properties.get(Constants.OBJECTCLASS);
-//                Long sid = (Long)properties.get(Constants.SERVICE_ID);
-//                properties = new PropertiesDictionary(props, classes, sid);
-//                Object new_rank = properties.get(Constants.SERVICE_RANKING);
-//                if (old_rank != new_rank && new_rank instanceof Integer &&
-//                    !((Integer)new_rank).equals(old_rank)) {
-//                  bundle.fwCtx.services.updateServiceRegistrationOrder(this, classes);
-//                }
-//              } else {
-//                throw new IllegalStateException("Service is unregistered");
-//              }
-//            }
-//          }
-//          bundle.fwCtx.listeners
-//            .serviceChanged(bundle.fwCtx.listeners.getMatchingServiceListeners(reference),
-//                            new ServiceEvent(ServiceEvent.MODIFIED, reference),
-//                            before);
-//          bundle.fwCtx.listeners
-//            .serviceChanged(before,
-//                            new ServiceEvent(ServiceEvent.MODIFIED_ENDMATCH, reference),
-//                            null);
+  Q_D(ctkServiceRegistration);
+  QMutexLocker lock(&d->eventLock);
+
+  QSet<ctkServiceSlotEntry> before;
+  // TBD, optimize the locking of services
+  {
+    QMutexLocker lock2(&d->plugin->fwCtx->globalFwLock);
+    QMutexLocker lock3(&d->propsLock);
+
+    if (d->available)
+    {
+      // NYI! Optimize the MODIFIED_ENDMATCH code
+      int old_rank = d->properties.value(ctkPluginConstants::SERVICE_RANKING).toInt();
+      before = d->plugin->fwCtx->listeners.getMatchingServiceSlots(d->reference);
+      QStringList classes = d->properties.value(ctkPluginConstants::OBJECTCLASS).toStringList();
+      qlonglong sid = d->properties.value(ctkPluginConstants::SERVICE_ID).toLongLong();
+      d->properties = ctkServices::createServiceProperties(props, classes, sid);
+      int new_rank = d->properties.value(ctkPluginConstants::SERVICE_RANKING).toInt();
+      if (old_rank != new_rank)
+      {
+        d->plugin->fwCtx->services.updateServiceRegistrationOrder(this, classes);
+      }
+    }
+    else
+    {
+      throw std::logic_error("Service is unregistered");
+    }
+  }
+  d->plugin->fwCtx->listeners.serviceChanged(
+      d->plugin->fwCtx->listeners.getMatchingServiceSlots(d->reference),
+      ctkServiceEvent(ctkServiceEvent::MODIFIED, d->reference), before);
 
+  d->plugin->fwCtx->listeners.serviceChanged(
+      before,
+      ctkServiceEvent(ctkServiceEvent::MODIFIED_ENDMATCH, d->reference));
 }
 
 void ctkServiceRegistration::unregister()
@@ -114,11 +118,9 @@ void ctkServiceRegistration::unregister()
 
   if (d->plugin)
   {
-    //TODO
-//      bundle.fwCtx.listeners
-//            .serviceChanged(bundle.fwCtx.listeners.getMatchingServiceListeners(reference),
-//                            new ServiceEvent(ServiceEvent.UNREGISTERING, reference),
-//                            null);
+     d->plugin->fwCtx->listeners.serviceChanged(
+         d->plugin->fwCtx->listeners.getMatchingServiceSlots(d->reference),
+         ctkServiceEvent(ctkServiceEvent::UNREGISTERING, d->reference));
   }
 
   {

+ 30 - 41
Libs/PluginFramework/ctkServices.cpp

@@ -29,10 +29,11 @@
 
 #include "ctkServiceFactory.h"
 #include "ctkPluginConstants.h"
+#include "ctkPluginFrameworkContext_p.h"
 #include "ctkServiceException.h"
 #include "ctkServiceRegistrationPrivate.h"
 #include "ctkQtServiceRegistration_p.h"
-#include "ctkLDAPExpr.h"
+#include "ctkLDAPExpr_p.h"
 
 
   using namespace QtMobility;
@@ -147,12 +148,10 @@ ctkServiceRegistration* ctkServices::registerService(ctkPluginPrivate* plugin,
     }
   }
 
-  //ctkServiceReference r = res->getReference();
-  // TODO
-  //Listeners l = bundle.fwCtx.listeners;
-  //l.serviceChanged(l.getMatchingServiceListeners(r),
-  //                 new ServiceEvent(ServiceEvent.REGISTERED, r),
-  //                 null);
+  ctkServiceReference r = res->getReference();
+  plugin->fwCtx->listeners.serviceChanged(
+      plugin->fwCtx->listeners.getMatchingServiceSlots(r),
+      ctkServiceEvent(ctkServiceEvent::REGISTERED, r));
   return res;
 }
 
@@ -225,12 +224,10 @@ void ctkServices::registerService(ctkPluginPrivate* plugin, QByteArray serviceDe
       s.insert(ip, res);
     }
 
-    //ctkServiceReference* r = res->getReference();
-    // TODO
-    //Listeners l = bundle.fwCtx.listeners;
-    //l.serviceChanged(l.getMatchingServiceListeners(r),
-    //                 new ServiceEvent(ServiceEvent.REGISTERED, r),
-    //                 null);
+    ctkServiceReference r = res->getReference();
+    plugin->fwCtx->listeners.serviceChanged(
+        plugin->fwCtx->listeners.getMatchingServiceSlots(r),
+        ctkServiceEvent(ctkServiceEvent::REGISTERED, r));
   }
 }
 
@@ -314,37 +311,30 @@ QList<ctkServiceReference> ctkServices::get(const QString& clazz, const QString&
   QMutexLocker lock(&mutex);
 
   QListIterator<ctkServiceRegistration*>* s = 0;
-  ctkLDAPExpr* ldap = 0;
+  QList<ctkServiceRegistration*> v;
+  ctkLDAPExpr ldap;
   if (clazz.isEmpty())
   {
     if (!filter.isEmpty())
     {
-      ldap = new ctkLDAPExpr(filter);
-      QSet<QString> matched = ldap->getMatchedObjectClasses();
+      ldap = ctkLDAPExpr(filter);
+      QSet<QString> matched = ldap.getMatchedObjectClasses();
       if (!matched.isEmpty())
       {
-        //TODO
-//        ArrayList v = null;
-//        boolean vReadOnly = true;;
-//        for (Iterator i = matched.iterator(); i.hasNext(); ) {
-//          ArrayList cl = (ArrayList) classServices.get(i.next());
-//          if (cl != null) {
-//            if (v == null) {
-//              v = cl;
-//            } else {
-//              if (vReadOnly) {
-//                v = new ArrayList(v);
-//                vReadOnly = false;
-//              }
-//              v.addAll(cl);
-//            }
-//          }
-//        }
-//        if (v != null) {
-//          s = v.iterator();
-//        } else {
-//          return null;
-//        }
+        v.clear();
+        foreach (QString className, matched)
+        {
+          const QList<ctkServiceRegistration*>& cl = classServices[className];
+          v += cl;
+        }
+        if (!v.isEmpty())
+        {
+          s = new QListIterator<ctkServiceRegistration*>(v);
+        }
+        else
+        {
+          return QList<ctkServiceReference>();
+        }
       }
       else
       {
@@ -369,7 +359,7 @@ QList<ctkServiceReference> ctkServices::get(const QString& clazz, const QString&
     }
     if (!filter.isEmpty())
     {
-      ldap = new ctkLDAPExpr(filter);
+      ldap = ctkLDAPExpr(filter);
     }
   }
 
@@ -379,14 +369,13 @@ QList<ctkServiceReference> ctkServices::get(const QString& clazz, const QString&
     ctkServiceRegistration* sr = s->next();
     ctkServiceReference sri = sr->getReference();
 
-    if (filter.isEmpty() || ldap->evaluate(sr->d_func()->properties, false))
+    if (filter.isEmpty() || ldap.evaluate(sr->d_func()->properties, false))
     {
       res.push_back(sri);
     }
   }
 
   delete s;
-  delete ldap;
 
   return res;
 }