1 /*=============================================================================
2 
3   Library: CTK
4 
5   Copyright (c) German Cancer Research Center,
6     Division of Medical and Biological Informatics
7 
8   Licensed under the Apache License, Version 2.0 (the "License");
9   you may not use this file except in compliance with the License.
10   You may obtain a copy of the License at
11 
12     http://www.apache.org/licenses/LICENSE-2.0
13 
14   Unless required by applicable law or agreed to in writing, software
15   distributed under the License is distributed on an "AS IS" BASIS,
16   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   See the License for the specific language governing permissions and
18   limitations under the License.
19 
20 =============================================================================*/
21 
22 #ifndef CTKPLUGINCONTEXT_H_
23 #define CTKPLUGINCONTEXT_H_
24 
25 #include <QHash>
26 #include <QString>
27 #include <QVariant>
28 #include <QUrl>
29 #include <QSharedPointer>
30 #include <QFileInfo>
31 
32 #include "ctkPluginFramework_global.h"
33 
34 #include "ctkPluginEvent.h"
35 #include "ctkServiceException.h"
36 #include "ctkServiceReference.h"
37 #include "ctkServiceRegistration.h"
38 
39 #include "ctkPluginFrameworkExport.h"
40 
41 
42 // CTK class forward declarations
43 class ctkPlugin;
44 class ctkPluginPrivate;
45 class ctkPluginContextPrivate;
46 
47 /**
48  * \ingroup PluginFramework
49  *
50  * A plugin's execution context within the Framework. The context is used to
51  * grant access to other methods so that this plugin can interact with the
52  * Framework.
53  *
54  * <p>
55  * <code>ctkPluginContext</code> methods allow a plugin to:
56  * <ul>
57  * <li>Subscribe to events published by the Framework.
58  * <li>Register service objects with the Framework service registry.
59  * <li>Retrieve <code>ServiceReferences</code> from the Framework service
60  * registry.
61  * <li>Get and release service objects for a referenced service.
62  * <li>Install new plugins in the Framework.
63  * <li>Get the list of plugins installed in the Framework.
64  * <li>Get the {@link ctkPlugin} object for a plugin.
65  * <li>Create <code>QFile</code> objects for files in a persistent storage
66  * area provided for the plugin by the Framework.
67  * </ul>
68  *
69  * <p>
70  * A <code>ctkPluginContext</code> object will be created and provided to the
71  * plugin associated with this context when it is started using the
72  * {@link ctkPluginActivator::start} method. The same <code>ctkPluginContext</code>
73  * object will be passed to the plugin associated with this context when it is
74  * stopped using the {@link ctkPluginActivator::stop} method. A
75  * <code>ctkPluginContext</code> object is generally for the private use of its
76  * associated plugin and is not meant to be shared with other plugins in the
77  * plugin environment.
78  *
79  * <p>
80  * The <code>ctkPlugin</code> object associated with a <code>ctkPluginContext</code>
81  * object is called the <em>context plugin</em>.
82  *
83  * <p>
84  * The <code>ctkPluginContext</code> object is only valid during the execution of
85  * its context plugin; that is, during the period from when the context plugin
86  * is in the <code>STARTING</code>, <code>STOPPING</code>, and
87  * <code>ACTIVE</code> plugin states. If the <code>ctkPluginContext</code>
88  * object is used subsequently, a <code>ctkIllegalStateException</code> must be
89  * thrown. The <code>ctkPluginContext</code> object must never be reused after
90  * its context plugin is stopped.
91  *
92  * <p>
93  * The Framework is the only entity that can create <code>ctkPluginContext</code>
94  * objects and they are only valid within the Framework that created them.
95  *
96  * @remarks This class is thread safe.
97  */
98 class CTK_PLUGINFW_EXPORT ctkPluginContext
99 {
100 
101 public:
102 
103   ~ctkPluginContext();
104 
105   /**
106    * Returns the value of the specified property. If the key is not found in
107    * the Framework properties, the system properties are then searched. The
108    * method returns an invalid QVariant if the property is not found.
109    *
110    * @param key The name of the requested property.
111    * @return The value of the requested property, or an invalid QVariant if
112    *         the property is undefined.
113    */
114   QVariant getProperty(const QString& key) const;
115 
116   /**
117    * Returns the <code>ctkPlugin</code> object associated with this
118    * <code>ctkPluginContext</code>. This plugin is called the context plugin.
119    *
120    * @return The <code>ctkPlugin</code> object associated with this
121    *         <code>ctkPluginContext</code>.
122    * @throws ctkIllegalStateException If this ctkPluginContext is no
123    *         longer valid.
124    */
125   QSharedPointer<ctkPlugin> getPlugin() const;
126 
127   /**
128    * Returns the plugin with the specified identifier.
129    *
130    * @param id The identifier of the plugin to retrieve.
131    * @return A <code>ctkPlugin</code> object or <code>0</code> if the
132    *         identifier does not match any installed plugin.
133    */
134   QSharedPointer<ctkPlugin> getPlugin(long id) const;
135 
136 
137   /**
138    * Returns a list of all installed plugins.
139    * <p>
140    * This method returns a list of all plugins installed in the plugin
141    * environment at the time of the call to this method. However, since the
142    * Framework is a very dynamic environment, plugins can be installed or
143    * uninstalled at anytime.
144    *
145    * @return A QList of <code>ctkPlugin</code> objects, one object per
146    *         installed plugin.
147    */
148   QList<QSharedPointer<ctkPlugin> > getPlugins() const;
149 
150   /**
151    * Registers the specified service object with the specified properties
152    * under the specified class names into the Framework. A
153    * <code>ctkServiceRegistration</code> object is returned. The
154    * <code>ctkServiceRegistration</code> object is for the private use of the
155    * plugin registering the service and should not be shared with other
156    * plugins. The registering plugin is defined to be the context plugin.
157    * Other plugins can locate the service by using either the
158    * {@link #getServiceReferences} or {@link #getServiceReference} method.
159    *
160    * <p>
161    * A plugin can register a service object that implements the
162    * {@link ctkServiceFactory} interface to have more flexibility in providing
163    * service objects to other plugins.
164    *
165    * <p>
166    * The following steps are required to register a service:
167    * <ol>
168    * <li>If <code>service</code> is not a <code>ctkServiceFactory</code>, an
169    * <code>ctkInvalidArgumentException</code> is thrown if <code>service</code>
170    * is not an instance of all the specified class names.
171    * <li>The Framework adds the following service properties to the service
172    * properties from the specified <code>ctkDictionary</code> (which may be
173    * omitted): <br/>
174    * A property named {@link ctkPluginConstants#SERVICE_ID} identifying the
175    * registration number of the service <br/>
176    * A property named {@link ctkPluginConstants#OBJECTCLASS} containing all the
177    * specified classes. <br/>
178    * Properties with these names in the specified <code>ctkDictionary</code> will
179    * be ignored.
180    * <li>The service is added to the Framework service registry and may now be
181    * used by other plugins.
182    * <li>A service event of type {@link ctkServiceEvent#REGISTERED} is fired.
183    * <li>A <code>ctkServiceRegistration</code> object for this registration is
184    * returned.
185    * </ol>
186    *
187    * @param clazzes The class names under which the service can be located.
188    *        The class names will be stored in the service's
189    *        properties under the key {@link ctkPluginConstants#OBJECTCLASS}.
190    * @param service The service object or a <code>ctkServiceFactory</code>
191    *        object.
192    * @param properties The properties for this service. The keys in the
193    *        properties object must all be <code>QString</code> objects. See
194    *        {@link ctkPluginConstants} for a list of standard service property keys.
195    *        Changes should not be made to this object after calling this
196    *        method. To update the service's properties the
197    *        {@link ctkServiceRegistration::setProperties} method must be called.
198    *        The set of properties may be omitted if the service has
199    *        no properties.
200    * @return A <code>ctkServiceRegistration</code> object for use by the plugin
201    *         registering the service to update the service's properties or to
202    *         unregister the service.
203    * @throws ctkInvalidArgumentException If one of the following is true:
204    *         <ul>
205    *         <li><code>service</code> is <code>0</code>. <li><code>service
206    *         </code> is not a <code>ctkServiceFactory</code> object and is not an
207    *         instance of all the named classes in <code>clazzes</code>. <li>
208    *         <code>properties</code> contains case variants of the same key
209    *         name.
210    *         </ul>
211    * @throws ctkIllegalStateException If this ctkPluginContext is no longer valid.
212    * @see ctkServiceRegistration
213    * @see ctkServiceFactory
214    */
215   ctkServiceRegistration registerService(const QStringList& clazzes, QObject* service, const ctkDictionary& properties = ctkDictionary());
216 
217   /**
218    * Registers the specified service object with the specified properties
219    * under the specified class name with the Framework.
220    *
221    * <p>
222    * This method is otherwise identical to
223    * registerService(const QStringList&, QObject*, const ctkDictionary&) and is provided as
224    * a convenience when <code>service</code> will only be registered under a single
225    * class name. Note that even in this case the value of the service's
226    * ctkPluginConstants::OBJECTCLASS property will be a QStringList, rather
227    * than just a single string.
228    *
229    * @param clazz The class name under which the service can be located.
230    * @param service The service object or a ctkServiceFactory object.
231    * @param properties The properties for this service.
232    * @return A ctkServiceRegistration object for use by the plugin
233    *         registering the service to update the service's properties or to
234    *         unregister the service.
235    * @throws ctkIllegalStateException If this ctkPluginContext is no longer valid.
236    * @see registerService(const QStringList&, QObject*, const ctkDictionary&)
237    */
238   ctkServiceRegistration registerService(const char* clazz, QObject* service, const ctkDictionary& properties = ctkDictionary());
239 
240   template<class S>
241   ctkServiceRegistration registerService(QObject* service, const ctkDictionary& properties = ctkDictionary())
242   {
243     const char* clazz = qobject_interface_iid<S*>();
244     if (clazz == 0)
245     {
246       throw ctkServiceException(QString("The interface class you are registering your service %1 against has no Q_DECLARE_INTERFACE macro")
247                                 .arg(service->metaObject()->className()));
248     }
249     return registerService(clazz, service, properties);
250   }
251 
252   /**
253    * Returns a list of <code>ctkServiceReference</code> objects. The returned
254    * list contains services that
255    * were registered under the specified class and match the specified filter
256    * expression.
257    *
258    * <p>
259    * The list is valid at the time of the call to this method. However since
260    * the Framework is a very dynamic environment, services can be modified or
261    * unregistered at any time.
262    *
263    * <p>
264    * The specified <code>filter</code> expression is used to select the
265    * registered services whose service properties contain keys and values
266    * which satisfy the filter expression. See {@link ctkLDAPSearchFilter} for a description
267    * of the filter syntax. If the specified <code>filter</code> is
268    * empty, all registered services are considered to match the
269    * filter. If the specified <code>filter</code> expression cannot be parsed,
270    * an <code>ctkInvalidArgumentException</code> will be thrown with a human readable
271    * message where the filter became unparsable.
272    *
273    * <p>
274    * The result is a list of <code>ctkServiceReference</code> objects for all
275    * services that meet all of the following conditions:
276    * <ul>
277    * <li>If the specified class name, <code>clazz</code>, is not
278    * empty, the service must have been registered with the
279    * specified class name. The complete list of class names with which a
280    * service was registered is available from the service's
281    * {@link ctkPluginConstants::OBJECTCLASS objectClass} property.
282    * <li>If the specified <code>filter</code> is not empty, the
283    * filter expression must match the service.
284    * </ul>
285    *
286    * @param clazz The class name with which the service was registered or
287    *        an empty string for all services.
288    * @param filter The filter expression or empty for all
289    *        services.
290    * @return A list of <code>ctkServiceReference</code> objects or
291    *         an empty list if no services are registered which satisfy the
292    *         search.
293    * @throws ctkInvalidArgumentException If the specified <code>filter</code>
294    *         contains an invalid filter expression that cannot be parsed.
295    * @throws ctkIllegalStateException If this ctkPluginContext is no longer valid.
296    */
297   QList<ctkServiceReference> getServiceReferences(const QString& clazz, const QString& filter = QString());
298 
299   /**
300    * Returns a list of <code>ctkServiceReference</code> objects. The returned
301    * list contains services that
302    * were registered under the Qt interface id of the template argument <code>S</code>
303    * and match the specified filter expression.
304    *
305    * <p>
306    * This method is identical to getServiceReferences(const QString&, const QString&) except that
307    * the class name for the service object is automatically deduced from the template argument.
308    *
309    * @param filter The filter expression or empty for all
310    *        services.
311    * @return A list of <code>ctkServiceReference</code> objects or
312    *         an empty list if no services are registered which satisfy the
313    *         search.
314    * @throws ctkInvalidArgumentException If the specified <code>filter</code>
315    *         contains an invalid filter expression that cannot be parsed.
316    * @throws ctkIllegalStateException If this ctkPluginContext is no longer valid.
317    * @see getServiceReferences(const QString&, const QString&)
318    */
319   template<class S>
320   QList<ctkServiceReference> getServiceReferences(const QString& filter = QString())
321   {
322     const char* clazz = qobject_interface_iid<S*>();
323     if (clazz == 0) throw ctkServiceException("The service interface class has no Q_DECLARE_INTERFACE macro");
324     return getServiceReferences(QString(clazz), filter);
325   }
326 
327   /**
328    * Returns a <code>ctkServiceReference</code> object for a service that
329    * implements and was registered under the specified class.
330    *
331    * <p>
332    * The returned <code>ctkServiceReference</code> object is valid at the time of
333    * the call to this method. However as the Framework is a very dynamic
334    * environment, services can be modified or unregistered at any time.
335    *
336    * <p>
337    * This method is the same as calling
338    * {@link ctkPluginContext::getServiceReferences(const QString&, const QString&)} with an
339    * empty filter expression. It is provided as a convenience for
340    * when the caller is interested in any service that implements the
341    * specified class.
342    * <p>
343    * If multiple such services exist, the service with the highest ranking (as
344    * specified in its {@link ctkPluginConstants::SERVICE_RANKING} property) is returned.
345    * <p>
346    * If there is a tie in ranking, the service with the lowest service ID (as
347    * specified in its {@link ctkPluginConstants::SERVICE_ID} property); that is, the
348    * service that was registered first is returned.
349    *
350    * @param clazz The class name with which the service was registered.
351    * @return A <code>ctkServiceReference</code> object, or <code>0</code> if
352    *         no services are registered which implement the named class.
353    * @throws ctkIllegalStateException If this ctkPluginContext is no longer valid.
354    * @throws ctkServiceException It no service was registered under the given class name.
355    * @see #getServiceReferences(const QString&, const QString&)
356    */
357   ctkServiceReference getServiceReference(const QString& clazz);
358 
359   /**
360    * Returns a <code>ctkServiceReference</code> object for a service that
361    * implements and was registered under the specified template class argument.
362    *
363    * <p>
364    * This method is identical to getServiceReference(const QString&) except that
365    * the class name for the service object is automatically deduced from the template argument.
366    *
367    * @return A <code>ctkServiceReference</code> object, or <code>0</code> if
368    *         no services are registered which implement the named class.
369    * @throws ctkIllegalStateException If this ctkPluginContext is no longer valid.
370    * @throws ctkServiceException It no service was registered under the given class name.
371    * @see #getServiceReference(const QString&)
372    * @see #getServiceReferences(const QString&)
373    */
374   template<class S>
getServiceReference()375   ctkServiceReference getServiceReference()
376   {
377     const char* clazz = qobject_interface_iid<S*>();
378     if (clazz == 0) throw ctkServiceException("The service interface class has no Q_DECLARE_INTERFACE macro");
379     return getServiceReference(QString(clazz));
380   }
381 
382   /**
383    * Returns the service object referenced by the specified
384    * <code>ctkServiceReference</code> object.
385    * <p>
386    * A plugin's use of a service is tracked by the plugin's use count of that
387    * service. Each time a service's service object is returned by
388    * {@link #getService(const ctkServiceReference&)} the context plugin's use count for
389    * that service is incremented by one. Each time the service is released by
390    * {@link #ungetService(const ctkServiceReference&)} the context plugin's use count
391    * for that service is decremented by one.
392    * <p>
393    * When a plugin's use count for a service drops to zero, the plugin should
394    * no longer use that service.
395    *
396    * <p>
397    * This method will always return <code>0</code> when the service
398    * associated with this <code>reference</code> has been unregistered.
399    *
400    * <p>
401    * The following steps are required to get the service object:
402    * <ol>
403    * <li>If the service has been unregistered, <code>0</code> is returned.
404    * <li>The context plugin's use count for this service is incremented by
405    * one.
406    * <li>If the context plugin's use count for the service is currently one
407    * and the service was registered with an object implementing the
408    * <code>ctkServiceFactory</code> interface, the
409    * {@link ctkServiceFactory::getService} method is
410    * called to create a service object for the context plugin. This service
411    * object is cached by the Framework. While the context plugin's use count
412    * for the service is greater than zero, subsequent calls to get the
413    * services's service object for the context plugin will return the cached
414    * service object. <br>
415    * If the service object returned by the <code>ctkServiceFactory</code> object
416    * is not an instance of all the classes named when the service
417    * was registered or the <code>ctkServiceFactory</code> object throws an
418    * exception, <code>0</code> is returned and a Framework event of type
419    * {@link ctkPluginFrameworkEvent::PLUGIN_ERROR} containing a {@link ctkServiceException}
420    * describing the error is fired.
421    * <li>The service object for the service is returned.
422    * </ol>
423    *
424    * @param reference A reference to the service.
425    * @return A service object for the service associated with
426    *         <code>reference</code> or <code>0</code> if the service is not
427    *         registered, the service object returned by a
428    *         <code>ctkServiceFactory</code> does not implement the classes under
429    *         which it was registered or the <code>ctkServiceFactory</code> threw
430    *         an exception.
431    * @throws ctkIllegalStateException If this ctkPluginContext is no
432    *         longer valid.
433    * @throws ctkInvalidArgumentException If the specified
434    *         <code>ctkServiceReference</code> was not created by the same
435    *         framework instance as this <code>ctkPluginContext</code> or
436    *         if it is invalid (default constructed).
437    * @see #ungetService(const ctkServiceReference&)
438    * @see ctkServiceFactory
439    */
440   QObject* getService(const ctkServiceReference& reference);
441 
442   /**
443    * Returns the service object referenced by the specified
444    * <code>ctkServiceReference</code> object.
445    * <p>
446    * This is a convenience method which is identical to QObject* getService(ctkServiceReference)
447    * except that it casts the service object to the supplied template argument type
448    *
449    * @return A service object for the service associated with
450    *         <code>reference</code> or <code>0</code> if the service is not
451    *         registered, the service object returned by a
452    *         <code>ctkServiceFactory</code> does not implement the classes under
453    *         which it was registered, the <code>ctkServiceFactory</code> threw
454    *         an exception or the service could not be casted to the desired type.
455    * @throws ctkIllegalStateException If this ctkPluginContext is no
456    *         longer valid.
457    * @throws ctkInvalidArgumentException If the specified
458    *         <code>ctkServiceReference</code> was not created by the same
459    *         framework instance as this <code>ctkPluginContext</code> or
460    *         if it is invalid (default constructed).
461    * @see #getService(const ctkServiceReference&)
462    * @see #ungetService(const ctkServiceReference&)
463    * @see ctkServiceFactory
464    */
465   template<class S>
getService(const ctkServiceReference & reference)466   S* getService(const ctkServiceReference& reference)
467   {
468     return qobject_cast<S*>(getService(reference));
469   }
470 
471   /**
472    * Releases the service object referenced by the specified
473    * <code>ctkServiceReference</code> object. If the context plugin's use count
474    * for the service is zero, this method returns <code>false</code>.
475    * Otherwise, the context plugins's use count for the service is decremented
476    * by one.
477    *
478    * <p>
479    * The service's service object should no longer be used and all references
480    * to it should be destroyed when a bundle's use count for the service drops
481    * to zero.
482    *
483    * <p>
484    * The following steps are required to unget the service object:
485    * <ol>
486    * <li>If the context plugin's use count for the service is zero or the
487    * service has been unregistered, <code>false</code> is returned.
488    * <li>The context plugin's use count for this service is decremented by
489    * one.
490    * <li>If the context plugin's use count for the service is currently zero
491    * and the service was registered with a <code>ctkServiceFactory</code> object,
492    * the
493    * {@link ctkServiceFactory#ungetService}
494    * method is called to release the service object for the context plugin.
495    * <li><code>true</code> is returned.
496    * </ol>
497    *
498    * @param reference A reference to the service to be released.
499    * @return <code>false</code> if the context plugin's use count for the
500    *         service is zero or if the service has been unregistered;
501    *         <code>true</code> otherwise.
502    * @throws ctkIllegalStateException If this ctkPluginContext is no
503    *         longer valid.
504    * @throws ctkInvalidArgumentException If the specified
505    *         <code>ctkServiceReference</code> was not created by the same
506    *         framework instance as this <code>ctkPluginContext</code>.
507    * @see #getService
508    * @see ctkServiceFactory
509    */
510   bool ungetService(const ctkServiceReference& reference);
511 
512   /**
513    * Creates a <code>QFileInfo</code> object for a file or directoryin the
514    * persistent storage area provided for the plugin by the Framework.
515    *
516    * <p>
517    * A <code>QFileInfo</code> object for the base directory of the persistent
518    * storage area provided for the context plugin by the Framework can be
519    * obtained by calling this method with an empty string as
520    * <code>filename</code>.
521    *
522    * <p>
523    * If the permissions are enabled, the Framework will
524    * ensure that the plugin has the <code>ctkFilePermission</code> with
525    * actions <code>read</code>,<code>write</code>,<code>delete</code>
526    * for all files (recursively) in the persistent storage area provided for
527    * the context plugin.
528    *
529    * @param filename A relative name to the file or directory to be accessed.
530    * @return A <code>QFileInfo</code> object that represents the requested file
531    *         or directory.
532    * @throws ctkIllegalStateException If this ctkPluginContext is no longer valid.
533    */
534   QFileInfo getDataFile(const QString& filename);
535 
536   /**
537    * Installs a plugin from the specified <code>QIODevice</code> object.
538    *
539    * <p>
540    * If the specified <code>QIODevice</code> is <code>null</code>, the
541    * Framework must create the <code>QIODevice</code> from which to read the
542    * plugin by interpreting, in an implementation dependent manner, the
543    * specified <code>location</code>.
544    *
545    * <p>
546    * The specified <code>location</code> identifier will be used as the
547    * identity of the plugin. Every installed plugin is uniquely identified by
548    * its location identifier which is typically in the form of a URL.
549    *
550    * <p>
551    * The following steps are required to install a plugin:
552    * <ol>
553    * <li>If a plugin containing the same location identifier is already
554    * installed, the <code>ctkPlugin</code> object for that plugin is returned.
555    *
556    * <li>The plugin's content is read from the input stream. If this fails, a
557    * {@link ctkPluginException} is thrown.
558    *
559    * <li>The plugin's associated resources are allocated. The associated
560    * resources minimally consist of a unique identifier and a persistent
561    * storage area. If this step fails, a <code>ctkPluginException</code>
562    * is thrown.
563    *
564    * <li>The plugin's state is set to <code>INSTALLED</code>.
565    *
566    * <li>A plugin event of type {@link ctkPluginEvent#INSTALLED} is fired.
567    *
568    * <li>The <code>ctkPlugin</code> object for the newly or previously installed
569    * plugin is returned.
570    * </ol>
571    *
572    * <b>Postconditions, no exceptions thrown </b>
573    * <ul>
574    * <li><code>getState()</code> in &#123; <code>INSTALLED</code>,
575    * <code>RESOLVED</code> &#125;.
576    * <li>Plugin has a unique ID.
577    * </ul>
578    * <b>Postconditions, when an exception is thrown </b>
579    * <ul>
580    * <li>Plugin is not installed and no trace of the plugin exists.
581    * </ul>
582    *
583    * @param location The location identifier of the plugin to install.
584    * @param input The <code>QIODevice</code> object from which this plugin
585    *        will be read or <code>null</code> to indicate the Framework must
586    *        create the I/O device from the specified location identifier.
587    *        The I/O device must always be closed when this method completes,
588    *        even if an exception is thrown.
589    * @return The <code>ctkPlugin</code> object of the installed plugin.
590    * @throws ctkPluginException If the I/O device cannot be read or the
591    *         installation failed.
592    * @throws ctkIllegalStateException If this ctkPluginContext is no longer valid.
593    */
594   QSharedPointer<ctkPlugin> installPlugin(const QUrl& location, QIODevice* input = 0);
595 
596   /**
597    * Connects the specified <code>slot</code> to the context
598    * plugins's signal which is emitted when a plugin has
599    * a lifecycle state change. The signature of the slot
600    * must be "slotName(ctkPluginEvent)".
601    *
602    * @param receiver The object to connect to.
603    * @param slot The slot to be connected.
604    * @param type The Qt connection type. Only Qt::DirectConnection,
605    *        Qt::QueuedConnection, or Qt::BlockingQueuedConnection is allowed.
606    * @returns <code>true</code> if the connection was successfull;
607    *          <code>false</code> otherwise.
608    * @throws ctkIllegalStateException If this ctkPluginContext is no
609    *         longer valid.
610    * @see ctkPluginEvent
611    * @see ctkEventBus
612    */
613   bool connectPluginListener(const QObject* receiver, const char* slot, Qt::ConnectionType type = Qt::QueuedConnection);
614 
615   /**
616    * Disconnects the specified <code>slot</code> from the context
617    * plugin.
618    *
619    * <p>
620    * If <code>slot</code> is not connected to the context plugin,
621    * this method does nothing.
622    *
623    * @param receiver The object which has previously connected <code>slot</code>.
624    * @param slot The Qt slot to be disconnected. If <code>NULL</code>, all slots
625    *        previously connected via connectPluginListener are disconnected.
626    * @throws ctkIllegalStateException If this ctkPluginContext is no longer valid.
627    */
628   void disconnectPluginListener(const QObject* receiver, const char* slot = 0);
629 
630   /**
631    * Connects the specified <code>slot</code> to the context
632    * plugin's signal which emits general Framework events. The signature
633    * of the slot must be "slotName(ctkPluginFrameworkEvent)".
634    *
635    * @param receiver The object to connect to.
636    * @param slot The slot to be connected.
637    * @param type The Qt connection type.
638    * @returns <code>true</code> if the connection was successfull;
639    *          <code>false</code> otherwise.
640    * @throws ctkIllegalStateException If this ctkPluginContext is no
641    *         longer valid.
642    * @see ctkPluginFrameworkEvent
643    * @see ctkEventBus
644    */
645   bool connectFrameworkListener(const QObject* receiver, const char* slot, Qt::ConnectionType type = Qt::QueuedConnection);
646 
647   /**
648    * Disconnects the specified <code>slot</code> from the context
649    * plugin.
650    *
651    * <p>
652    * If <code>slot</code> is not connected to the context plugin,
653    * this method does nothing.
654    *
655    * @param receiver The object which has previously connected <code>slot</code>.
656    * @param slot The Qt slot to be disconnected. If <code>NULL</code>, all slots
657    *        previously connected via connectFrameworkListener are disconnected.
658    * @throws ctkIllegalStateException If this ctkPluginContext is no longer valid.
659    */
660   void disconnectFrameworkListener(const QObject* receiver, const char* slot = 0);
661 
662   /**
663    * Connects the specified <code>slot</code> with the
664    * specified <code>filter</code> to the context plugins's signal emitting
665    * service events when a service has a lifecycle state change. The signature
666    * of the slot must be "slotName(const ctkServiceEvent&)", but only the name
667    * of the slot must be provided as the argument.
668    * See {@link ctkLDAPSearchFilter} for a description of
669    * the filter syntax.
670    *
671    * <p>
672    * If the object to connect to is destroyed, the slot is automatically
673    * disconnected. To explicitly disconnect the slot, use
674    * disconnectServiceListener().
675    *
676    * <p>
677    * If the context plugin's list of listeners already contains the same
678    * slot for the given receiver, then this
679    * method replaces that slot's filter (which may be <code>null</code>)
680    * with the specified one (which may be <code>null</code>).
681    *
682    * <p>
683    * The slot is called if the filter criteria is met. To filter based
684    * upon the class of the service, the filter should reference the
685    * {@link ctkPluginConstants#OBJECTCLASS} property. If <code>filter</code> is
686    * <code>null</code>, all services are considered to match the filter.
687    *
688    * <p>
689    * When using a <code>filter</code>, it is possible that the
690    * <code>ctkServiceEvent</code>s for the complete lifecycle of a service
691    * will not be delivered to the slot. For example, if the
692    * <code>filter</code> only matches when the property <code>x</code> has
693    * the value <code>1</code>, the listener will not be called if the
694    * service is registered with the property <code>x</code> not set to the
695    * value <code>1</code>. Subsequently, when the service is modified
696    * setting property <code>x</code> to the value <code>1</code>, the
697    * filter will match and the slot will be called with a
698    * <code>ServiceEvent</code> of type <code>MODIFIED</code>. Thus, the
699    * slot will not be called with a <code>ServiceEvent</code> of type
700    * <code>REGISTERED</code>.
701    *
702    * @param receiver The object to connect to.
703    * @param slot The name of the slot to be connected.
704    * @param filter The filter criteria.
705    * @throws ctkInvalidArgumentException If <code>filter</code> contains an
706    *         invalid filter string that cannot be parsed.
707    * @throws ctkIllegalStateException If this ctkPluginContext is no
708    *         longer valid.
709    * @see ctkServiceEvent
710    * @see disconnectServiceListener()
711    * @see ctkEventBus
712    */
713   void connectServiceListener(QObject* receiver, const char* slot,
714                               const QString& filter = QString());
715 
716   /**
717    * Disconnects a slot which has been previously connected
718    * with a call to connectServiceListener().
719    *
720    * @param receiver The object containing the slot.
721    * @param slot The slot to be disconnected.
722    * @see connectServiceListener()
723    */
724   void disconnectServiceListener(QObject* receiver, const char* slot);
725 
726 protected:
727 
728   friend class ctkPluginFrameworkPrivate;
729   friend class ctkPlugin;
730   friend class ctkPluginPrivate;
731 
732   ctkPluginContext(ctkPluginPrivate* plugin);
733 
734   ctkPluginContextPrivate * const d_ptr;
735 
736 private:
737   Q_DECLARE_PRIVATE(ctkPluginContext)
738 };
739 
740 
741 #endif /* CTKPLUGINCONTEXT_H_ */
742