瀏覽代碼

ENH: PluginFramework: Renamed PluginFrameworkContext to PluginFrameworkFactory and added more documentation.

Sascha Zelzer 15 年之前
父節點
當前提交
af23af6bd1

+ 3 - 5
Applications/ctkPluginBrowser/ctkPluginBrowserMain.cxx

@@ -19,7 +19,7 @@
 
 =============================================================================*/
 
-#include <ctkPluginFrameworkContext.h>
+#include <ctkPluginFrameworkFactory.h>
 #include <ctkPluginFramework.h>
 #include <ctkPluginException.h>
 
@@ -33,11 +33,9 @@ int main(int argv, char** argc)
 {
   QApplication app(argv, argc);
 
-  PluginFrameworkContext::Properties props;
+  PluginFrameworkFactory fwFactory;
+  PluginFramework* framework = fwFactory.getFramework();
 
-  PluginFrameworkContext fwContext(props);
-
-  PluginFramework* framework = fwContext.getFramework();
   try {
     framework->init();
   }

+ 2 - 1
Documentation/Doxyfile.txt.in

@@ -660,7 +660,8 @@ RECURSIVE              = YES
 # subdirectory from a directory tree whose root is specified with the INPUT tag.
 
 EXCLUDE                = @CTK_BINARY_DIR@ \
-                         @CTK_SOURCE_DIR@/CMake
+                         @CTK_SOURCE_DIR@/CMake \
+                         @CTK_SOURCE_DIR@/Utilities
 
 # The EXCLUDE_SYMLINKS tag can be used select whether or not files or
 # directories that are symbolic links (a Unix filesystem feature) are excluded

+ 1 - 1
Libs/PluginFramework/CMakeLists.txt

@@ -51,8 +51,8 @@ SET(KIT_SRCS
   ctkPluginEvent.cxx
   ctkPluginException.cxx
   ctkPluginFramework.cxx
+  ctkPluginFrameworkFactory.cxx
   ctkPluginFrameworkContext.cxx
-  ctkPluginFrameworkContextPrivate.cxx
   ctkPluginFrameworkEvent.cxx
   ctkPluginFrameworkListeners.cxx
   ctkPluginFrameworkPrivate.cxx

+ 2 - 2
Libs/PluginFramework/ctkPlugin.cxx

@@ -23,13 +23,13 @@
 
 #include "ctkPluginPrivate_p.h"
 #include "ctkPluginArchive_p.h"
-#include "ctkPluginFrameworkContextPrivate_p.h"
+#include "ctkPluginFrameworkContext_p.h"
 
 #include <QStringList>
 
 namespace ctk {
 
-  Plugin::Plugin(PluginFrameworkContextPrivate* fw,
+  Plugin::Plugin(PluginFrameworkContext* fw,
                  PluginArchive* pa)
     : d_ptr(new PluginPrivate(*this, fw, pa))
   {

+ 28 - 28
Libs/PluginFramework/ctkPlugin.h

@@ -29,16 +29,16 @@
 namespace ctk {
 
   class PluginArchive;
-  class PluginFrameworkContextPrivate;
+  class PluginFrameworkContext;
   class PluginPrivate;
 
   /**
    * An installed plugin in the Framework.
    *
    * <p>
-   * A <code>Plugin</code> object is the access point to define the lifecycle of
+   * A <code>%Plugin</code> object is the access point to define the lifecycle of
    * an installed plugin. Each plugin installed in the plugin environment must have
-   * an associated <code>Plugin</code> object.
+   * an associated <code>%Plugin</code> object.
    *
    * <p>
    * A plugin must have a unique identity, a <code>long</code>, chosen by the
@@ -62,13 +62,13 @@ namespace ctk {
    *
    * <p>
    * A plugin should only execute code when its state is one of
-   * <code>STARTING</code>,<code>ACTIVE</code>, or <code>STOPPING</code>.
+   * <code>STARTING</code>, <code>ACTIVE</code>, or <code>STOPPING</code>.
    * An <code>UNINSTALLED</code> plugin can not be set to another state; it is a
    * zombie and can only be reached because references are kept somewhere.
    *
    * <p>
    * The Framework is the only entity that is allowed to create
-   * <code>Plugin</code> objects, and these objects are only valid within the
+   * <code>%Plugin</code> objects, and these objects are only valid within the
    * Framework that created them.
    *
    * @threadsafe
@@ -86,7 +86,7 @@ namespace ctk {
        * <p>
        * The <code>UNINSTALLED</code> state is only visible after a plugin is
        * uninstalled; the plugin is in an unusable state but references to the
-       * <code>Plugin</code> object may still be available and used for
+       * <code>%Plugin</code> object may still be available and used for
        * introspection.
        */
       UNINSTALLED,
@@ -114,7 +114,7 @@ namespace ctk {
        * include:
        * <ul>
        * <li>The plugin's required plugin dependencies from its
-       * {@link PluginConstants#REQUIRE_PLUGIN} Manifest header.
+       * {@link PluginConstants::REQUIRE_PLUGIN} Manifest header.
        * </ul>
        * <p>
        * Note that the plugin is not active yet. A plugin must be put in the
@@ -129,7 +129,7 @@ namespace ctk {
        * <p>
        * A plugin is in the <code>STARTING</code> state when its
        * {@link #start(const Options&) start} method is active. A plugin must be in this
-       * state when the plugin's {@link PluginActivator#start} method is called. If the
+       * state when the plugin's {@link PluginActivator::start} method is called. If the
        * <code>PluginActivator::start</code> method completes without exception,
        * then the plugin has successfully started and must move to the
        * <code>ACTIVE</code> state.
@@ -147,7 +147,7 @@ namespace ctk {
        * <p>
        * A plugin is in the <code>STOPPING</code> state when its
        * {@link #stop(const Option&) stop} method is active. A plugin must be in this state
-       * when the plugin's {@link PluginActivator#stop} method is called. When the
+       * when the plugin's {@link PluginActivator::stop} method is called. When the
        * <code>PluginActivator::stop</code> method completes the plugin is
        * stopped and must move to the <code>RESOLVED</code> state.
        */
@@ -281,7 +281,7 @@ namespace ctk {
      * <li>If this plugin's state is <code>STARTING</code> then this method
      * returns immediately.
      * <li>This plugin's state is set to <code>STARTING</code>.
-     * <li>A plugin event of type {@link PluginEvent#LAZY_ACTIVATION} is fired.
+     * <li>A plugin event of type {@link PluginEvent::LAZY_ACTIVATION} is fired.
      * <li>This method returns immediately and the remaining steps will be
      * followed when this plugin's activation is later triggered.
      * </ul>
@@ -291,43 +291,43 @@ namespace ctk {
      * <i></i>
      * <li>This plugin's state is set to <code>STARTING</code>.
      *
-     * <li>A plugin event of type {@link PluginEvent#STARTING} is fired.
+     * <li>A plugin event of type {@link PluginEvent::STARTING} is fired.
      *
-     * <li>The {@link PluginActivator#start} method of this plugin's
+     * <li>The {@link PluginActivator::start} method of this plugin's
      * <code>PluginActivator</code>, is called. If the
      * <code>PluginActivator</code> throws an exception then:
      * <ul>
      * <li>This plugin's state is set to <code>STOPPING</code>.
-     * <li>A plugin event of type {@link PluginEvent#STOPPING} is fired.
+     * <li>A plugin event of type {@link PluginEvent::STOPPING} is fired.
      * <li>Any services registered by this plugin must be unregistered.
      * <li>Any services used by this plugin must be released.
      * <li>Any listeners registered by this plugin must be removed.
      * <li>This plugin's state is set to <code>RESOLVED</code>.
-     * <li>A plugin event of type {@link BundleEvent#STOPPED} is fired.
+     * <li>A plugin event of type {@link PluginEvent::STOPPED} is fired.
      * <li>A <code>PluginException</code> is then thrown.
      * </ul>
      * <i></i>
      * <li>If this plugin's state is <code>UNINSTALLED</code>, because this
-     * plugin was uninstalled while the <code>PluginActivator#start</code>
+     * plugin was uninstalled while the <code>PluginActivator::start</code>
      * method was running, a <code>PluginException</code> is thrown.
      *
      * <li>This plugin's state is set to <code>ACTIVE</code>.
      *
-     * <li>A plugin event of type {@link PluginEvent#STARTED} is fired.
+     * <li>A plugin event of type {@link PluginEvent::STARTED} is fired.
      * </ol>
      *
      * <b>Preconditions </b>
      * <ul>
-     * <li><code>getState()</code> in &#x007B; <code>INSTALLED</code>,
-     * <code>RESOLVED</code>, <code>STARTING</code> &#x007D;
-     * or &#x007B; <code>INSTALLED</code>, <code>RESOLVED</code> &#x007D;
+     * <li><code>getState()</code> in { <code>INSTALLED</code>,
+     * <code>RESOLVED</code>, <code>STARTING</code> }
+     * or { <code>INSTALLED</code>, <code>RESOLVED</code> }
      * if this plugin has a eager activation policy.
      * </ul>
      * <b>Postconditions, no exceptions thrown </b>
      * <ul>
-     * <li>Plugin autostart setting is modified unless the
+     * <li>%Plugin autostart setting is modified unless the
      * {@link #START_TRANSIENT} option was set.
-     * <li><code>getState()</code> in &#x007B; <code>ACTIVE</code> &#x007D;
+     * <li><code>getState()</code> in { <code>ACTIVE</code> }
      * if the eager activation policy was used.
      * <li><code>PluginActivator::start()</code> has been called and did not
      * throw an exception if the eager policy was used.
@@ -336,8 +336,8 @@ namespace ctk {
      * <ul>
      * <li>Depending on when the exception occurred, plugin autostart setting is
      * modified unless the {@link #START_TRANSIENT} option was set.
-     * <li><code>getState()</code> not in &#x007B; <code>STARTING</code>,
-     * <code>ACTIVE</code> &#x007D;.
+     * <li><code>getState()</code> not in { <code>STARTING</code>,
+     * <code>ACTIVE</code> }.
      * </ul>
      *
      * @param options The options for starting this plugin. See
@@ -376,7 +376,7 @@ namespace ctk {
      *
      * <li>This plugin's state is set to <code>STOPPING</code>.
      *
-     * <li>A plugin event of type {@link PluginEvent#STOPPING} is fired.
+     * <li>A plugin event of type {@link PluginEvent::STOPPING} is fired.
      *
      * <li>If this plugin's state was <code>ACTIVE</code> prior to setting the
      * state to <code>STOPPING</code>, the {@link PluginActivator#stop} method
@@ -395,12 +395,12 @@ namespace ctk {
      *
      * <li>This plugin's state is set to <code>RESOLVED</code>.
      *
-     * <li>A plugin event of type {@link PluginEvent#STOPPED} is fired.
+     * <li>A plugin event of type {@link PluginEvent::STOPPED} is fired.
      * </ol>
      *
      * <b>Preconditions </b>
      * <ul>
-     * <li><code>getState()</code> in &#x007B; <code>ACTIVE</code> &#x007D;.
+     * <li><code>getState()</code> in { <code>ACTIVE</code> }.
      * </ul>
      * <b>Postconditions, no exceptions thrown </b>
      * <ul>
@@ -587,12 +587,12 @@ namespace ctk {
   protected:
 
     friend class PluginFramework;
-    friend class PluginFrameworkContextPrivate;
+    friend class PluginFrameworkContext;
     friend class Plugins;
 
     PluginPrivate * const d_ptr;
 
-    Plugin(PluginFrameworkContextPrivate* fw, PluginArchive* ba);
+    Plugin(PluginFrameworkContext* fw, PluginArchive* ba);
     Plugin(PluginPrivate& dd);
   };
 

+ 78 - 5
Libs/PluginFramework/ctkPluginActivator.h

@@ -24,23 +24,96 @@
 
 #include "ctkPluginContext.h"
 
-#include "CTKPluginFrameworkExport.h"
-
 namespace ctk {
 
+  /**
+   * Customizes the starting and stopping of a plugin.
+   * <p>
+   * <code>%PluginActivator</code> is an interface that must be implemented by
+   * every plugin in the Framework. The Framework can create instances of a
+   * plugin's <code>%PluginActivator</code> as required. If an instance's
+   * <code>PluginActivator::start</code> method executes successfully, it is
+   * guaranteed that the same instance's <code>PluginActivator::stop</code>
+   * method will be called when the plugin is to be stopped. The Framework must
+   * not concurrently call a <code>%PluginActivator</code> object.
+   *
+   * <p>
+   * <code>%PluginActivator</code> is a Qt interface which must be implemented
+   * using the standard Qt %Plugin facilities:
+   *
+   * <p>
+   * <pre>
+   * class MyPlugin : public QObject, public %ctk::PluginActivator
+   * {
+   *   Q_OBJECT
+   *   Q_INTERFACES(ctk::PluginActivator)
+   *
+   * public:
+   *   void %start(%ctk::PluginContext* context);
+   *   void %stop(%ctk::PluginContext* context);
+   * };
+   * </pre>
+   * And in your implementation file:
+   * <pre>
+   * Q_EXPORT_PLUGIN2(mypluginlib, MyPlugin)
+   * </pre>
+   * where <code>mypluginlib</code> is the basename of your shared plugin library.
+   *
+   * <p>
+   * See the Qt Documentation about <a href="http://doc.trolltech.com/4.6/plugins-howto.html">
+   * How to Create Qt Plugins</a> for details.
+   *
+   * The class implementing the <code>%PluginActivator</code> interface must have a public
+   * constructor that takes no parameters so that a <code>%PluginActivator</code>
+   * object can be created by <code>QPluginLoader::instance</code>.
+   *
+   */
   class PluginActivator
   {
   public:
 
-    virtual ~PluginActivator() {};
-
+    virtual ~PluginActivator() {}
+
+    /**
+     * Called when this plugin is started so the Framework can perform the
+     * plugin-specific activities necessary to start this plugin. This method
+     * can be used to register services or to allocate any resources that this
+     * plugin needs.
+     *
+     * <p>
+     * This method must complete and return to its caller in a timely manner.
+     *
+     * @param context The execution context of the plugin being started.
+     * @throws std::exception If this method throws an exception, this
+     *         plugin is marked as stopped and the Framework will remove this
+     *         plugin's listeners, unregister all services registered by this
+     *         plugin, and release all services used by this plugin.
+     */
     virtual void start(PluginContext* context) = 0;
+
+    /**
+     * Called when this plugin is stopped so the Framework can perform the
+     * plugin-specific activities necessary to stop the plugin. In general, this
+     * method should undo the work that the <code>PluginActivator::start</code>
+     * method started. There should be no active threads that were started by
+     * this plugin when this plugin returns. A stopped plugin must not call any
+     * Framework objects.
+     *
+     * <p>
+     * This method must complete and return to its caller in a timely manner.
+     *
+     * @param context The execution context of the plugin being stopped.
+     * @throws std::exception If this method throws an exception, the
+     *         plugin is still marked as stopped, and the Framework will remove
+     *         the plugin's listeners, unregister all services registered by the
+     *         plugin, and release all services used by the plugin.
+     */
     virtual void stop(PluginContext* context) = 0;
 
   };
 
 }
 
-Q_DECLARE_INTERFACE(ctk::PluginActivator, "org.commontk.core.pluginactivator")
+Q_DECLARE_INTERFACE(ctk::PluginActivator, "org.commontk.pluginfw.pluginactivator")
 
 #endif /* CTKPLUGINACTIVATOR_H_ */

+ 1 - 1
Libs/PluginFramework/ctkPluginConstants.h

@@ -118,7 +118,7 @@ namespace ctk {
      * by the plugin.
      *
      * <p>
-     * The attribute value may be retrieved from the <code>Dictionary</code>
+     * The attribute value may be retrieved from the <code>QHash</code>
      * object returned by the <code>Plugin::getHeaders</code> method.
      *
      */

+ 1 - 1
Libs/PluginFramework/ctkPluginContext.cxx

@@ -22,7 +22,7 @@
 #include "ctkPluginContext.h"
 
 #include "ctkPluginPrivate_p.h"
-#include "ctkPluginFrameworkContextPrivate_p.h"
+#include "ctkPluginFrameworkContext_p.h"
 #include "ctkServiceRegistration.h"
 #include "ctkServiceReference.h"
 

+ 2 - 2
Libs/PluginFramework/ctkPluginContext.h

@@ -64,9 +64,9 @@ namespace ctk {
    * <p>
    * A <code>PluginContext</code> 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 <code>PluginContext</code>
+   * {@link PluginActivator::start} method. The same <code>PluginContext</code>
    * object will be passed to the plugin associated with this context when it is
-   * stopped using the {@link PluginActivator#stop} method. A
+   * stopped using the {@link PluginActivator::stop} method. A
    * <code>PluginContext</code> 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.

+ 3 - 8
Libs/PluginFramework/ctkPluginFramework.cxx

@@ -23,14 +23,14 @@
 
 #include "ctkPluginFrameworkPrivate_p.h"
 #include "ctkPluginPrivate_p.h"
-#include "ctkPluginFrameworkContextPrivate_p.h"
+#include "ctkPluginFrameworkContext_p.h"
 #include "ctkPluginConstants.h"
 #include "ctkPluginArchive_p.h"
 
 
 namespace ctk {
 
-  PluginFramework::PluginFramework(PluginFrameworkContextPrivate* fw)
+  PluginFramework::PluginFramework(PluginFrameworkContext* fw)
     : Plugin(*new PluginFrameworkPrivate(*this, fw))
   {
     qRegisterMetaType<PluginFrameworkEvent>("PluginFrameworkEvent");
@@ -41,7 +41,7 @@ namespace ctk {
     Q_D(PluginFramework);
 
     QMutexLocker sync(&d->lock);
-    // waitOnActivation(d->lock, "Framework.ini", true);
+    // waitOnActivation(d->lock, "Framework.init", true);
     switch (d->state)
     {
     case Plugin::INSTALLED:
@@ -152,11 +152,6 @@ namespace ctk {
     return resourceFile.readAll();
   }
 
-  void waitForStop(int timeout)
-  {
-    // TODO implement
-  }
-
   QHash<QString, QString> PluginFramework::getHeaders()
   {
     //TODO security

+ 62 - 9
Libs/PluginFramework/ctkPluginFramework.h

@@ -29,9 +29,19 @@
 
 namespace ctk {
 
-  class PluginFrameworkContextPrivate;
+  class PluginFrameworkContext;
   class PluginFrameworkPrivate;
 
+  /**
+   * A %PluginFramework instance. A %PluginFramework is also known as a System %Plugin.
+   *
+   * <p>
+   * %PluginFramework instances are created using a PluginFrameworkFactory. The methods
+   * of this class can be used to manage and control the created plugin framework
+   * instance.
+   *
+   * @threadsafe
+   */
   class CTK_PLUGINFW_EXPORT PluginFramework : public Plugin
   {
 
@@ -40,30 +50,73 @@ namespace ctk {
   public:
 
     /**
-     * Initialize this framework.
+     * Initialize this %PluginFramework. After calling this method, this %PluginFramework
+     * must:
+     * <ul>
+     * <li>Be in the {@link #STARTING} state.</li>
+     * <li>Have a valid Plugin Context.</li>
+     * <li>Be at start level 0.</li>
+     * <li>Have event handling enabled.</li>
+     * <li>Have create Plugin objects for all installed plugins.</li>
+     * <li>Have registered any framework services.</li>
+     * </ul>
+     *
+     * <p>
+     * This %PluginFramework will not actually be started until {@link #start() start}
+     * is called.
+     *
+     * <p>
+     * This method does nothing if called when this %PluginFramework is in the
+     * {@link #STARTING}, {@link #ACTIVE} or {@link #STOPPING} states.
+     *
+     * @throws PluginException If this %PluginFramework could not be initialized.
      */
     void init();
 
     /**
-     * Start this framework.
+     * Start this %PluginFramework.
+     *
+     * <p>
+     * The following steps are taken to start this %PluginFramework:
+     * <ol>
+     * <li>If this %PluginFramework is not in the {@link #STARTING} state,
+     * {@link #init() initialize} this %PluginFramework.</li>
+     * <li>All installed plugins must be started in accordance with each
+     * plugin's persistent <i>autostart setting</i>. This means some plugins
+     * will not be started, some will be started with <i>lazy activation</i>
+     * and some will be started with their <i>declared activation</i> policy.
+     * Any exceptions that occur during plugin starting must be wrapped in a
+     * {@link PluginException} and then published as a plugin framework event of type
+     * {@link PluginFrameworkEvent::ERROR}</li>
+     * <li>This %PluinFramework's state is set to {@link #ACTIVE}.</li>
+     * <li>A plugin framework event of type {@link PluginFrameworkEvent::STARTED} is fired</li>
+     * </ol>
+     *
+     * @param options Ignored. There are no start options for the %PluginFramework.
+     * @throws PluginException If this %PluginFramework could not be started.
      */
     void start(const Plugin::StartOptions& options = 0);
 
+    /**
+     * @see Plugin::getHeaders()
+     */
     QHash<QString, QString> getHeaders();
 
-    // TODO return info about the reason why this
-    // method returned
-    void waitForStop(int timeout);
-
+    /**
+     * @see Plugin::getResourceList()
+     */
     QStringList getResourceList(const QString& path) const;
 
+    /**
+     * @see Plugin::getResource()
+     */
     QByteArray getResource(const QString& path) const;
 
   protected:
 
-    friend class PluginFrameworkContextPrivate;
+    friend class PluginFrameworkContext;
 
-    PluginFramework(PluginFrameworkContextPrivate* fw);
+    PluginFramework(PluginFrameworkContext* fw);
 
   };
 

+ 148 - 9
Libs/PluginFramework/ctkPluginFrameworkContext.cxx

@@ -19,27 +19,166 @@
 
 =============================================================================*/
 
-#include "ctkPluginFrameworkContext.h"
+#include "ctkPluginFrameworkContext_p.h"
 
-#include "ctkPluginFrameworkContextPrivate_p.h"
+#include "ctkPluginFrameworkPrivate_p.h"
+#include "ctkPluginArchive_p.h"
+#include "ctkPluginConstants.h"
 
 namespace ctk {
 
-  PluginFrameworkContext::PluginFrameworkContext(const Properties& initProps)
-    : d_ptr(new PluginFrameworkContextPrivate(initProps))
+  QMutex PluginFrameworkContext::globalFwLock;
+  int PluginFrameworkContext::globalId = 1;
+
+
+  PluginFrameworkContext::PluginFrameworkContext(
+      const PluginFrameworkFactory::Properties& initProps)
+        : plugins(0), /*services(this),*/ systemPlugin(this),
+        storage(this), props(initProps)
+  {
+
+    {
+      QMutexLocker lock(&globalFwLock);
+      id = globalId++;
+    }
+
+    log() << "created";
+  }
+
+  void PluginFrameworkContext::init()
+  {
+    log() << "initializing";
+
+//    if (Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT
+//        .equals(props.getProperty(Constants.FRAMEWORK_STORAGE_CLEAN))) {
+//      deleteFWDir();
+//      // Must remove the storage clean property since it should not be
+//      // used more than once!
+//      props.removeProperty(Constants.FRAMEWORK_STORAGE_CLEAN);
+//    }
+//    props.save();
+
+    PluginFrameworkPrivate* const systemPluginPrivate = systemPlugin.d_func();
+    systemPluginPrivate->initSystemPlugin();
+
+    plugins = new Plugins(this);
+
+    plugins->load();
+
+    log() << "inited";
+
+    log() << "Installed plugins:";
+    // Use the ordering in the plugin storage to get a sorted list of plugins.
+    QList<PluginArchive*> allPAs = storage.getAllPluginArchives();
+    for (int i = 0; i < allPAs.size(); ++i)
+    {
+      PluginArchive* pa = allPAs[i];
+      Plugin* p = plugins->getPlugin(pa->getPluginLocation().toString());
+      log() << " #" << p->getPluginId() << " " << p->getSymbolicName() << ":"
+          << p->getVersion() << " location:" << p->getLocation();
+    }
+  }
+
+  void PluginFrameworkContext::uninit()
+  {
+    log() << "uninit";
+
+    //PluginFrameworkPrivate* const systemPluginPrivate = systemPlugin.d_func();
+    //systemPluginPrivate->uninitSystemBundle();
+
+    plugins->clear();
+    delete plugins;
+    plugins = 0;
+
+    storage.close();
+
+  }
+
+  int PluginFrameworkContext::getId() const
   {
+    return id;
+  }
+
+  void PluginFrameworkContext::checkOurPlugin(Plugin* plugin) const
+  {
+    PluginPrivate* pp = plugin->d_func();
+    if (this != pp->fwCtx)
+    {
+      throw std::invalid_argument("Plugin does not belong to this framework: " + plugin->getSymbolicName().toStdString());
+    }
+  }
 
+  QDebug PluginFrameworkContext::log() const
+  {
+    QDebug dbg(qDebug());
+    dbg << "Framework instance " << getId() << ": ";
+    return dbg;
   }
 
-  PluginFrameworkContext::~PluginFrameworkContext()
+  void PluginFrameworkContext::resolvePlugin(PluginPrivate* plugin)
   {
-    delete d_ptr;
+    qDebug() << "resolve:" << plugin->symbolicName << "[" << plugin->id << "]";
+
+    // If we enter with tempResolved set, it means that we already have
+    // resolved plugins. Check that it is true!
+    if (tempResolved.size() > 0 && !tempResolved.contains(plugin))
+    {
+      PluginException pe("resolve: InternalError1!", PluginException::RESOLVE_ERROR);
+      listeners.frameworkError(plugin->q_func(), pe);
+      throw pe;
+    }
+
+    tempResolved.clear();
+    tempResolved.insert(plugin);
+
+    checkRequirePlugin(plugin);
+
+    tempResolved.clear();
+
+    qDebug() << "resolve: Done for" << plugin->symbolicName << "[" << plugin->id << "]";
   }
 
-  PluginFramework* PluginFrameworkContext::getFramework()
+  void PluginFrameworkContext::checkRequirePlugin(PluginPrivate *plugin)
   {
-    Q_D(PluginFrameworkContext);
-    return &(d->systemPlugin);
+    if (!plugin->require.isEmpty())
+    {
+      qDebug() << "checkRequirePlugin: check requiring plugin" << plugin->id;
+
+      QListIterator<RequirePlugin*> i(plugin->require);
+      while (i.hasNext())
+      {
+        RequirePlugin* pr = i.next();
+        QList<Plugin*> pl = plugins->getPlugins(pr->name, pr->pluginRange);
+        PluginPrivate* ok = 0;
+        for (QListIterator<Plugin*> pci(pl); pci.hasNext() && ok == 0; )
+        {
+          PluginPrivate* p2 = pci.next()->d_func();
+          if (tempResolved.contains(p2))
+          {
+            ok = p2;
+          }
+          else if (PluginPrivate::RESOLVED_FLAGS & p2->state)
+          {
+            ok = p2;
+          }
+          else if (p2->state == Plugin::INSTALLED) {
+            QSet<PluginPrivate*> oldTempResolved = tempResolved;
+            tempResolved.insert(p2);
+            checkRequirePlugin(p2);
+            tempResolved = oldTempResolved;
+            ok = p2;
+          }
+        }
+
+        if (!ok && pr->resolution == PluginConstants::RESOLUTION_MANDATORY)
+        {
+          tempResolved.clear();
+          qDebug() << "checkRequirePlugin: failed to satisfy:" << pr->name;
+          throw PluginException(QString("Failed to resolve required plugin: %1").arg(pr->name));
+        }
+      }
+    }
   }
 
+
 }

+ 0 - 184
Libs/PluginFramework/ctkPluginFrameworkContextPrivate.cxx

@@ -1,184 +0,0 @@
-/*=============================================================================
-
-  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 "ctkPluginFrameworkContextPrivate_p.h"
-
-#include "ctkPluginFrameworkPrivate_p.h"
-#include "ctkPluginArchive_p.h"
-#include "ctkPluginConstants.h"
-
-namespace ctk {
-
-  QMutex PluginFrameworkContextPrivate::globalFwLock;
-  int PluginFrameworkContextPrivate::globalId = 1;
-
-
-  PluginFrameworkContextPrivate::PluginFrameworkContextPrivate(
-      const PluginFrameworkContext::Properties& initProps)
-        : plugins(0), /*services(this),*/ systemPlugin(this),
-        storage(this), props(initProps)
-  {
-
-    {
-      QMutexLocker lock(&globalFwLock);
-      id = globalId++;
-    }
-
-    log() << "created";
-  }
-
-  void PluginFrameworkContextPrivate::init()
-  {
-    log() << "initializing";
-
-//    if (Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT
-//        .equals(props.getProperty(Constants.FRAMEWORK_STORAGE_CLEAN))) {
-//      deleteFWDir();
-//      // Must remove the storage clean property since it should not be
-//      // used more than once!
-//      props.removeProperty(Constants.FRAMEWORK_STORAGE_CLEAN);
-//    }
-//    props.save();
-
-    PluginFrameworkPrivate* const systemPluginPrivate = systemPlugin.d_func();
-    systemPluginPrivate->initSystemPlugin();
-
-    plugins = new Plugins(this);
-
-    plugins->load();
-
-    log() << "inited";
-
-    log() << "Installed plugins:";
-    // Use the ordering in the plugin storage to get a sorted list of plugins.
-    QList<PluginArchive*> allPAs = storage.getAllPluginArchives();
-    for (int i = 0; i < allPAs.size(); ++i)
-    {
-      PluginArchive* pa = allPAs[i];
-      Plugin* p = plugins->getPlugin(pa->getPluginLocation().toString());
-      log() << " #" << p->getPluginId() << " " << p->getSymbolicName() << ":"
-          << p->getVersion() << " location:" << p->getLocation();
-    }
-  }
-
-  void PluginFrameworkContextPrivate::uninit()
-  {
-    log() << "uninit";
-
-    //PluginFrameworkPrivate* const systemPluginPrivate = systemPlugin.d_func();
-    //systemPluginPrivate->uninitSystemBundle();
-
-    plugins->clear();
-    delete plugins;
-    plugins = 0;
-
-    storage.close();
-
-  }
-
-  int PluginFrameworkContextPrivate::getId() const
-  {
-    return id;
-  }
-
-  void PluginFrameworkContextPrivate::checkOurPlugin(Plugin* plugin) const
-  {
-    PluginPrivate* pp = plugin->d_func();
-    if (this != pp->fwCtx)
-    {
-      throw std::invalid_argument("Plugin does not belong to this framework: " + plugin->getSymbolicName().toStdString());
-    }
-  }
-
-  QDebug PluginFrameworkContextPrivate::log() const
-  {
-    QDebug dbg(qDebug());
-    dbg << "Framework instance " << getId() << ": ";
-    return dbg;
-  }
-
-  void PluginFrameworkContextPrivate::resolvePlugin(PluginPrivate* plugin)
-  {
-    qDebug() << "resolve:" << plugin->symbolicName << "[" << plugin->id << "]";
-
-    // If we enter with tempResolved set, it means that we already have
-    // resolved plugins. Check that it is true!
-    if (tempResolved.size() > 0 && !tempResolved.contains(plugin))
-    {
-      PluginException pe("resolve: InternalError1!", PluginException::RESOLVE_ERROR);
-      listeners.frameworkError(plugin->q_func(), pe);
-      throw pe;
-    }
-
-    tempResolved.clear();
-    tempResolved.insert(plugin);
-
-    checkRequirePlugin(plugin);
-
-    tempResolved.clear();
-
-    qDebug() << "resolve: Done for" << plugin->symbolicName << "[" << plugin->id << "]";
-  }
-
-  void PluginFrameworkContextPrivate::checkRequirePlugin(PluginPrivate *plugin)
-  {
-    if (!plugin->require.isEmpty())
-    {
-      qDebug() << "checkRequirePlugin: check requiring plugin" << plugin->id;
-
-      QListIterator<RequirePlugin*> i(plugin->require);
-      while (i.hasNext())
-      {
-        RequirePlugin* pr = i.next();
-        QList<Plugin*> pl = plugins->getPlugins(pr->name, pr->pluginRange);
-        PluginPrivate* ok = 0;
-        for (QListIterator<Plugin*> pci(pl); pci.hasNext() && ok == 0; )
-        {
-          PluginPrivate* p2 = pci.next()->d_func();
-          if (tempResolved.contains(p2))
-          {
-            ok = p2;
-          }
-          else if (PluginPrivate::RESOLVED_FLAGS & p2->state)
-          {
-            ok = p2;
-          }
-          else if (p2->state == Plugin::INSTALLED) {
-            QSet<PluginPrivate*> oldTempResolved = tempResolved;
-            tempResolved.insert(p2);
-            checkRequirePlugin(p2);
-            tempResolved = oldTempResolved;
-            ok = p2;
-          }
-        }
-
-        if (!ok && pr->resolution == PluginConstants::RESOLUTION_MANDATORY)
-        {
-          tempResolved.clear();
-          qDebug() << "checkRequirePlugin: failed to satisfy:" << pr->name;
-          throw PluginException(QString("Failed to resolve required plugin: %1").arg(pr->name));
-        }
-      }
-    }
-  }
-
-
-}

+ 7 - 7
Libs/PluginFramework/ctkPluginFrameworkContextPrivate_p.h

@@ -19,13 +19,13 @@
 
 =============================================================================*/
 
-#ifndef CTKPLUGINFRAMEWORKCONTEXTPRIVATE_P_H
-#define CTKPLUGINFRAMEWORKCONTEXTPRIVATE_P_H
+#ifndef CTKPLUGINFRAMEWORKCONTEXT_P_H
+#define CTKPLUGINFRAMEWORKCONTEXT_P_H
 
 #include <QDebug>
 #include <QMutex>
 
-#include "ctkPluginFrameworkContext.h"
+#include "ctkPluginFrameworkFactory.h"
 #include "ctkPluginFramework.h"
 #include "ctkPluginStorage_p.h"
 #include "ctkPlugins_p.h"
@@ -35,7 +35,7 @@ namespace ctk {
 
   class Plugin;
 
-  class PluginFrameworkContextPrivate {
+  class PluginFrameworkContext {
 
   public:
 
@@ -79,13 +79,13 @@ namespace ctk {
        */
       static int globalId;
 
-      PluginFrameworkContext::Properties props;
+      PluginFrameworkFactory::Properties props;
 
       /**
        * Contruct a framework context
        *
        */
-      PluginFrameworkContextPrivate(const PluginFrameworkContext::Properties& initProps);
+      PluginFrameworkContext(const PluginFrameworkFactory::Properties& initProps);
 
 
       /**
@@ -141,4 +141,4 @@ namespace ctk {
 
 }
 
-#endif // CTKPLUGINFRAMEWORKCONTEXTPRIVATE_P_H
+#endif // CTKPLUGINFRAMEWORKCONTEXT_P_H

+ 14 - 27
Libs/PluginFramework/ctkPluginFrameworkContext.h

@@ -19,39 +19,26 @@
 
 =============================================================================*/
 
-#ifndef CTKPLUGINFRAMEWORKCONTEXT_H
-#define CTKPLUGINFRAMEWORKCONTEXT_H
+#include "ctkPluginFrameworkFactory.h"
 
-#include <QHash>
-#include <QString>
-#include <QVariant>
-
-#include "CTKPluginFrameworkExport.h"
+#include "ctkPluginFrameworkContext_p.h"
 
 namespace ctk {
 
-  class PluginFramework;
-  class PluginFrameworkContextPrivate;
-
-  class CTK_PLUGINFW_EXPORT PluginFrameworkContext {
-
-    Q_DECLARE_PRIVATE(PluginFrameworkContext)
-
-  public:
+  PluginFrameworkFactory::PluginFrameworkFactory(const Properties& initProps)
+    : fwCtx(new PluginFrameworkContext(initProps))
+  {
 
-    typedef QHash<QString, QVariant> Properties;
+  }
 
-    PluginFrameworkContext(const Properties& initProps);
-    ~PluginFrameworkContext();
+  PluginFrameworkFactory::~PluginFrameworkFactory()
+  {
+    delete fwCtx;
+  }
 
-    PluginFramework* getFramework();
-
-  private:
-
-    PluginFrameworkContextPrivate * const d_ptr;
-
-  };
+  PluginFramework* PluginFrameworkFactory::getFramework()
+  {
+    return &(fwCtx->systemPlugin);
+  }
 
 }
-
-#endif // CTKPLUGINFRAMEWORKCONTEXT_H

+ 82 - 0
Libs/PluginFramework/ctkPluginFrameworkFactory.h

@@ -0,0 +1,82 @@
+/*=============================================================================
+
+  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 CTKPLUGINFRAMEWORKFACTORY_H
+#define CTKPLUGINFRAMEWORKFACTORY_H
+
+#include <QHash>
+#include <QString>
+#include <QVariant>
+
+#include "CTKPluginFrameworkExport.h"
+
+namespace ctk {
+
+  class PluginFramework;
+  class PluginFrameworkContext;
+
+  /**
+   * A factory for creating PluginFramework instances.
+   */
+  class CTK_PLUGINFW_EXPORT PluginFrameworkFactory {
+
+  public:
+
+    typedef QHash<QString, QVariant> Properties;
+
+    /**
+     * Create a new <code>%PluginFrameworkFactory</code> instance.
+     *
+     * <p>
+     * The Properties map is used to configure the PluginFramework. The
+     * plugin framework instance created with #getFramework() must interpret
+     * the following properties:
+     *
+     * <p>
+     * <ul><li>PluginConstants::FRAMEWORK_STORAGE</li>
+     * </ul>
+     *
+     * @param initProps The plugin framework configuration properties.
+     *        The PluginFramework instance created with #getFramework()
+     *        must use some reasonable default configuration if certain
+     *        properties are not provided.
+     */
+    PluginFrameworkFactory(const Properties& initProps = Properties());
+
+    ~PluginFrameworkFactory();
+
+    /**
+     * Create a new PluginFramework instance.
+     *
+     * @return A new, configured PluginFramework instance. The plugin
+     *         framework instance must be in the Plugin::INSTALLED state.
+     */
+    PluginFramework* getFramework();
+
+  private:
+
+    PluginFrameworkContext * const fwCtx;
+
+  };
+
+}
+
+#endif // CTKPLUGINFRAMEWORKFACTORY_H

+ 2 - 2
Libs/PluginFramework/ctkPluginFrameworkPrivate.cxx

@@ -24,11 +24,11 @@
 #include "ctkPluginFramework.h"
 #include "ctkPluginConstants.h"
 
-#include "ctkPluginFrameworkContextPrivate_p.h"
+#include "ctkPluginFrameworkContext_p.h"
 
 namespace ctk {
 
-  PluginFrameworkPrivate::PluginFrameworkPrivate(PluginFramework& qq, PluginFrameworkContextPrivate* fw)
+  PluginFrameworkPrivate::PluginFrameworkPrivate(PluginFramework& qq, PluginFrameworkContext* fw)
     : PluginPrivate(qq, fw, 0, PluginConstants::SYSTEM_PLUGIN_LOCATION,
                     PluginConstants::SYSTEM_PLUGIN_SYMBOLICNAME,
                     // TODO: read version from the manifest resource

+ 3 - 2
Libs/PluginFramework/ctkPluginFrameworkPrivate_p.h

@@ -23,12 +23,13 @@
 #define CTKPLUGINFRAMEWORKPRIVATE_P_H
 
 #include "ctkPluginPrivate_p.h"
+#include "ctkPluginFramework.h"
 
 #include <QMutex>
 
 namespace ctk {
 
-  class PluginFramework;
+  class PluginFrameworkContext;
 
   class PluginFrameworkPrivate : public PluginPrivate
   {
@@ -36,7 +37,7 @@ namespace ctk {
 
     QMutex lock;
 
-    PluginFrameworkPrivate(PluginFramework& qq, PluginFrameworkContextPrivate* fw);
+    PluginFrameworkPrivate(PluginFramework& qq, PluginFrameworkContext* fw);
 
     void init();
 

+ 3 - 3
Libs/PluginFramework/ctkPluginPrivate.cxx

@@ -24,7 +24,7 @@
 #include "ctkPluginConstants.h"
 #include "ctkPluginDatabaseException.h"
 #include "ctkPluginArchive_p.h"
-#include "ctkPluginFrameworkContextPrivate_p.h"
+#include "ctkPluginFrameworkContext_p.h"
 #include "ctkPluginFrameworkUtil_p.h"
 #include "ctkPluginActivator.h"
 
@@ -35,7 +35,7 @@ namespace ctk {
 
   PluginPrivate::PluginPrivate(
       Plugin& qq,
-      PluginFrameworkContextPrivate* fw,
+      PluginFrameworkContext* fw,
       PluginArchive* pa)
     : q_ptr(&qq), fwCtx(fw), id(pa->getPluginId()),
     location(pa->getPluginLocation().toString()), state(Plugin::INSTALLED),
@@ -65,7 +65,7 @@ namespace ctk {
   }
 
   PluginPrivate::PluginPrivate(Plugin& qq,
-    PluginFrameworkContextPrivate* fw,
+    PluginFrameworkContext* fw,
     long id, const QString& loc, const QString& sym, const Version& ver)
       : q_ptr(&qq), fwCtx(fw), id(id), location(loc), symbolicName(sym), version(ver),
       state(Plugin::INSTALLED), archive(0), pluginContext(0),

+ 5 - 5
Libs/PluginFramework/ctkPluginPrivate_p.h

@@ -33,7 +33,7 @@ namespace ctk {
 
   class PluginActivator;
   class PluginArchive;
-  class PluginFrameworkContextPrivate;
+  class PluginFrameworkContext;
 
   class PluginPrivate {
 
@@ -53,7 +53,7 @@ namespace ctk {
      * @param checkContext AccessConrolContext to do permission checks against.
      * @exception std::invalid_argument Faulty manifest for bundle
      */
-    PluginPrivate(Plugin& qq, PluginFrameworkContextPrivate* fw,
+    PluginPrivate(Plugin& qq, PluginFrameworkContext* fw,
                PluginArchive* pa /*, Object checkContext*/);
 
     /**
@@ -64,7 +64,7 @@ namespace ctk {
      * @param fw Framework for this plugin.
      */
     PluginPrivate(Plugin& qq,
-                  PluginFrameworkContextPrivate* fw,
+                  PluginFrameworkContext* fw,
                   long id,
                   const QString& loc,
                   const QString& sym,
@@ -97,7 +97,7 @@ namespace ctk {
      */
     static const Plugin::States RESOLVED_FLAGS;
 
-    PluginFrameworkContextPrivate * const fwCtx;
+    PluginFrameworkContext * const fwCtx;
 
     /**
      * Plugin identifier
@@ -179,7 +179,7 @@ namespace ctk {
 
   private:
 
-    friend class PluginFrameworkContextPrivate;
+    friend class PluginFrameworkContext;
 
     /**
      * Check manifest and cache certain manifest headers as variables.

+ 2 - 2
Libs/PluginFramework/ctkPluginStorage.cxx

@@ -28,12 +28,12 @@
 
 // CTK includes
 #include "ctkPluginArchive_p.h"
-#include "ctkPluginFrameworkContextPrivate_p.h"
+#include "ctkPluginFrameworkContext_p.h"
 #include "ctkPluginDatabaseException.h"
 
 namespace ctk {
 
-  PluginStorage::PluginStorage(PluginFrameworkContextPrivate* framework)
+  PluginStorage::PluginStorage(PluginFrameworkContext* framework)
     : framework(framework), pluginDatabase(this)
   {
 //    // See if we have a storage database

+ 3 - 3
Libs/PluginFramework/ctkPluginStorage_p.h

@@ -34,7 +34,7 @@ namespace ctk {
 
   // CTK class forward declarations
   class PluginArchive;
-  class PluginFrameworkContextPrivate;
+  class PluginFrameworkContext;
 
   /**
    * Storage of all plugin meta-data and resources
@@ -53,7 +53,7 @@ namespace ctk {
     /**
      * Framework handle.
      */
-    PluginFrameworkContextPrivate* framework;
+    PluginFrameworkContext* framework;
 
     /**
      * SQLite db caching plug-in metadata and resources
@@ -67,7 +67,7 @@ namespace ctk {
      * Try to restore all saved plugin archive state.
      *
      */
-    PluginStorage(PluginFrameworkContextPrivate* framework);
+    PluginStorage(PluginFrameworkContext* framework);
 
 
     /**

+ 2 - 2
Libs/PluginFramework/ctkPlugins.cxx

@@ -24,7 +24,7 @@
 #include "ctkPluginPrivate_p.h"
 #include "ctkPluginArchive_p.h"
 #include "ctkPluginException.h"
-#include "ctkPluginFrameworkContextPrivate_p.h"
+#include "ctkPluginFrameworkContext_p.h"
 #include "ctkVersionRange_p.h"
 
 #include <stdexcept>
@@ -34,7 +34,7 @@
 
 namespace ctk {
 
-  Plugins::Plugins(PluginFrameworkContextPrivate* fw) {
+  Plugins::Plugins(PluginFrameworkContext* fw) {
     fwCtx = fw;
     plugins.insert(fw->systemPlugin.getLocation(), &fw->systemPlugin);
   }

+ 3 - 3
Libs/PluginFramework/ctkPlugins_p.h

@@ -31,7 +31,7 @@ namespace ctk {
 
   // CTK class forward declarations
   class Plugin;
-  class PluginFrameworkContextPrivate;
+  class PluginFrameworkContext;
   class Version;
   class VersionRange;
 
@@ -53,7 +53,7 @@ namespace ctk {
     /**
      * Link to framework object.
      */
-    PluginFrameworkContextPrivate* fwCtx;
+    PluginFrameworkContext* fwCtx;
 
     /**
      * Read write lock for protecting the plugins object
@@ -66,7 +66,7 @@ namespace ctk {
     /**
      * Create a container for all plugins in this framework.
      */
-    Plugins(PluginFrameworkContextPrivate* fw);
+    Plugins(PluginFrameworkContext* fw);
 
 
     void clear();