/*============================================================================= 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 CTKPLUGINCONTEXT_H_ #define CTKPLUGINCONTEXT_H_ #include #include #include #include #include "ctkPluginFramework_global.h" #include "ctkPluginEvent.h" #include "CTKPluginFrameworkExport.h" namespace ctk { // CTK class forward declarations class Plugin; class PluginPrivate; class ServiceRegistration; class ServiceReference; class PluginContextPrivate; /** * A plugin's execution context within the Framework. The context is used to * grant access to other methods so that this plugin can interact with the * Framework. * *

* PluginContext methods allow a plugin to: *

    *
  • Subscribe to events published by the Framework. *
  • Register service objects with the Framework service registry. *
  • Retrieve ServiceReferences from the Framework service * registry. *
  • Get and release service objects for a referenced service. *
  • Install new plugins in the Framework. *
  • Get the list of plugins installed in the Framework. *
  • Get the {@link Plugin} object for a plugin. *
  • Create QFile objects for files in a persistent storage * area provided for the plugin by the Framework. *
* *

* A PluginContext object will be created and provided to the * plugin associated with this context when it is started using the * {@link PluginActivator::start} method. The same PluginContext * object will be passed to the plugin associated with this context when it is * stopped using the {@link PluginActivator::stop} method. A * PluginContext object is generally for the private use of its * associated plugin and is not meant to be shared with other plugins in the * plugin environment. * *

* The Plugin object associated with a PluginContext * object is called the context plugin. * *

* The PluginContext object is only valid during the execution of * its context plugin; that is, during the period from when the context plugin * is in the STARTING, STOPPING, and * ACTIVE plugin states. If the PluginContext * object is used subsequently, a std::logic_error must be * thrown. The PluginContext object must never be reused after * its context plugin is stopped. * *

* The Framework is the only entity that can create PluginContext * objects and they are only valid within the Framework that created them. * * @threadsafe */ class CTK_PLUGINFW_EXPORT PluginContext { Q_DECLARE_PRIVATE(PluginContext) public: ~PluginContext(); /** * Returns the Plugin object associated with this * PluginContext. This plugin is called the context plugin. * * @return The Plugin object associated with this * PluginContext. * @throws std::logic_error If this PluginContext is no * longer valid. */ Plugin* getPlugin() const; /** * Returns the plugin with the specified identifier. * * @param id The identifier of the plugin to retrieve. * @return A Plugin object or 0 if the * identifier does not match any installed plugin. */ Plugin* getPlugin(long id) const; /** * Returns a list of all installed plugins. *

* This method returns a list of all plugins installed in the plugin * environment at the time of the call to this method. However, since the * Framework is a very dynamic environment, plugins can be installed or * uninstalled at anytime. * * @return A QList of Plugin objects, one object per * installed plugin. */ QList getPlugins() const; /** * Registers the specified service object with the specified properties * under the specified class names into the Framework. A * ServiceRegistration object is returned. The * ServiceRegistration object is for the private use of the * plugin registering the service and should not be shared with other * plugins. The registering plugin is defined to be the context plugin. * Other plugins can locate the service by using either the * {@link #getServiceReferences} or {@link #getServiceReference} method. * *

* A plugin can register a service object that implements the * {@link ServiceFactory} interface to have more flexibility in providing * service objects to other plugins. * *

* The following steps are required to register a service: *

    *
  1. If service is not a ServiceFactory, an * std::invalid_argument is thrown if service * is not an instance of all the specified class names. *
  2. The Framework adds the following service properties to the service * properties from the specified ServiceProperties (which may be * omitted):
    * A property named {@link PluginConstants#SERVICE_ID} identifying the * registration number of the service
    * A property named {@link PluginConstants#OBJECTCLASS} containing all the * specified classes.
    * Properties with these names in the specified ServiceProperties will * be ignored. *
  3. The service is added to the Framework service registry and may now be * used by other plugins. *
  4. A service event of type {@link ServiceEvent#REGISTERED} is fired. *
  5. A ServiceRegistration object for this registration is * returned. *
* * @param clazzes The class names under which the service can be located. * The class names will be stored in the service's * properties under the key {@link PluginConstants#OBJECTCLASS}. * @param service The service object or a ServiceFactory * object. * @param properties The properties for this service. The keys in the * properties object must all be QString objects. See * {@link PluginConstants} for a list of standard service property keys. * Changes should not be made to this object after calling this * method. To update the service's properties the * {@link ServiceRegistration::setProperties} method must be called. * The set of properties may be omitted if the service has * no properties. * @return A ServiceRegistration object for use by the plugin * registering the service to update the service's properties or to * unregister the service. * @throws std::invalid_argument If one of the following is true: *
    *
  • service is 0.
  • service * is not a ServiceFactory object and is not an * instance of all the named classes in clazzes.
  • * properties contains case variants of the same key * name. *
* @throws std::logic_error If this PluginContext is no longer valid. * @see ServiceRegistration * @see ServiceFactory */ ServiceRegistration* registerService(const QStringList& clazzes, QObject* service, const ServiceProperties& properties = ServiceProperties()); /** * Returns a list of ServiceReference objects. The returned * list contains services that * were registered under the specified class and match the specified filter * expression. * *

* The list is valid at the time of the call to this method. However since * the Framework is a very dynamic environment, services can be modified or * unregistered at any time. * *

* The specified filter expression is used to select the * registered services whose service properties contain keys and values * which satisfy the filter expression. See {@link Filter} for a description * of the filter syntax. If the specified filter is * empty, all registered services are considered to match the * filter. If the specified filter expression cannot be parsed, * an {@link std::invalid_argument} will be thrown with a human readable * message where the filter became unparsable. * *

* The result is a list of ServiceReference objects for all * services that meet all of the following conditions: *

    *
  • If the specified class name, clazz, is not * empty, the service must have been registered with the * specified class name. The complete list of class names with which a * service was registered is available from the service's * {@link PlugincConstants::OBJECTCLASS objectClass} property. *
  • If the specified filter is not empty, the * filter expression must match the service. *
* * @param clazz The class name with which the service was registered or * an empty string for all services. * @param filter The filter expression or empty for all * services. * @return A list of ServiceReference objects or * an empty list if no services are registered which satisfy the * search. * @throws std::invalid_argument If the specified filter * contains an invalid filter expression that cannot be parsed. * @throws std::logic_error If this PluginContext is no longer valid. */ QList getServiceReferences(const QString& clazz, const QString& filter = QString()); /** * Returns a ServiceReference object for a service that * implements and was registered under the specified class. * *

* The returned ServiceReference object is valid at the time of * the call to this method. However as the Framework is a very dynamic * environment, services can be modified or unregistered at any time. * *

* This method is the same as calling * {@link PluginContext::getServiceReferences(const QString&, const QString&)} with an * empty filter expression. It is provided as a convenience for * when the caller is interested in any service that implements the * specified class. *

* If multiple such services exist, the service with the highest ranking (as * specified in its {@link PluginConstants::SERVICE_RANKING} property) is returned. *

* If there is a tie in ranking, the service with the lowest service ID (as * specified in its {@link PluginConstants::SERVICE_ID} property); that is, the * service that was registered first is returned. * * @param clazz The class name with which the service was registered. * @return A ServiceReference object, or 0 if * no services are registered which implement the named class. * @throws std::logic_error If this PluginContext is no longer valid. * @see #getServiceReferences(const QString&, const QString&) */ ServiceReference* getServiceReference(const QString& clazz); /** * Returns the service object referenced by the specified * ServiceReference object. *

* A plugin's use of a service is tracked by the plugin's use count of that * service. Each time a service's service object is returned by * {@link #getService(ServiceReference*)} the context plugin's use count for * that service is incremented by one. Each time the service is released by * {@link #ungetService(ServiceReference*)} the context plugin's use count * for that service is decremented by one. *

* When a plugin's use count for a service drops to zero, the plugin should * no longer use that service. * *

* This method will always return 0 when the service * associated with this reference has been unregistered. * *

* The following steps are required to get the service object: *

    *
  1. If the service has been unregistered, 0 is returned. *
  2. The context plugin's use count for this service is incremented by * one. *
  3. If the context plugin's use count for the service is currently one * and the service was registered with an object implementing the * ServiceFactory interface, the * {@link ServiceFactory::getService(Plugin*, ServiceRegistration*)} method is * called to create a service object for the context plugin. This service * object is cached by the Framework. While the context plugin's use count * for the service is greater than zero, subsequent calls to get the * services's service object for the context plugin will return the cached * service object.
    * If the service object returned by the ServiceFactory object * is not an instance of all the classes named when the service * was registered or the ServiceFactory object throws an * exception, 0 is returned and a Framework event of type * {@link FrameworkEvent::ERROR} containing a {@link ServiceException} * describing the error is fired. *
  4. The service object for the service is returned. *
* * @param reference A reference to the service. * @return A service object for the service associated with * reference or 0 if the service is not * registered, the service object returned by a * ServiceFactory does not implement the classes under * which it was registered or the ServiceFactory threw * an exception. * @throws std::logic_error If this PluginContext is no * longer valid. * @throws std::invalid_argument If the specified * ServiceReference was not created by the same * framework instance as this PluginContext. * @see #ungetService(ServiceReference*) * @see ServiceFactory */ QObject* getService(ServiceReference* reference); Plugin* installPlugin(const QUrl& location, QIODevice* in = 0); bool connectPluginListener(const QObject* receiver, const char* method, Qt::ConnectionType type = Qt::QueuedConnection); bool connectFrameworkListener(const QObject* receiver, const char* method, Qt::ConnectionType type = Qt::QueuedConnection); protected: friend class PluginFrameworkPrivate; friend class Plugin; friend class PluginPrivate; PluginContext(PluginPrivate* plugin); PluginContextPrivate * const d_ptr; }; } #endif /* CTKPLUGINCONTEXT_H_ */