ctkPlugins.cpp

Go to the documentation of this file.
00001 /*=============================================================================
00002 
00003   Library: CTK
00004 
00005   Copyright (c) 2010 German Cancer Research Center,
00006     Division of Medical and Biological Informatics
00007 
00008   Licensed under the Apache License, Version 2.0 (the "License");
00009   you may not use this file except in compliance with the License.
00010   You may obtain a copy of the License at
00011 
00012     http://www.apache.org/licenses/LICENSE-2.0
00013 
00014   Unless required by applicable law or agreed to in writing, software
00015   distributed under the License is distributed on an "AS IS" BASIS,
00016   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00017   See the License for the specific language governing permissions and
00018   limitations under the License.
00019 
00020 =============================================================================*/
00021 
00022 #include "ctkPlugins_p.h"
00023 
00024 #include "ctkPluginPrivate_p.h"
00025 #include "ctkPluginArchive_p.h"
00026 #include "ctkPluginException.h"
00027 #include "ctkPluginFrameworkContext_p.h"
00028 #include "ctkVersionRange_p.h"
00029 
00030 #include <stdexcept>
00031 #include <iostream>
00032 
00033 #include <QUrl>
00034 
00035 
00036   ctkPlugins::ctkPlugins(ctkPluginFrameworkContext* fw) {
00037     fwCtx = fw;
00038     plugins.insert(fw->systemPlugin.getLocation(), &fw->systemPlugin);
00039   }
00040 
00041   void ctkPlugins::clear()
00042   {
00043     QWriteLocker lock(&pluginsLock);
00044     plugins.clear();
00045     fwCtx = 0;
00046   }
00047 
00048   ctkPlugin* ctkPlugins::install(const QUrl& location, QIODevice* in)
00049   {
00050     if (!fwCtx)
00051     { // This ctkPlugins instance has been closed!
00052       throw std::logic_error("ctkPlugins::install(location, inputStream) called on closed plugins object.");
00053     }
00054 
00055     {
00056       QWriteLocker lock(&pluginsLock);
00057 
00058       QHash<QString, ctkPlugin*>::const_iterator it = plugins.find(location.toString());
00059       if (it != plugins.end()) {
00060         return it.value();
00061       }
00062 
00063       // install new plugin
00064       ctkPluginArchive* pa = 0;
00065       QString localPluginPath;
00066       try {
00067         if (!in) {
00068           // extract the input stream from the given location
00069           
00070 
00071 //          //TODO Support for http proxy authentication
00072 //          //TODO put in update as well
00073 //          String auth = fwCtx.props.getProperty("http.proxyAuth");
00074 //          if (auth != null && !"".equals(auth)) {
00075 //            if ("http".equals(url.getProtocol()) ||
00076 //                "https".equals(url.getProtocol())) {
00077 //              String base64 = Util.base64Encode(auth);
00078 //              conn.setRequestProperty("Proxy-Authorization",
00079 //                                      "Basic " + base64);
00080 //            }
00081 //          }
00082 //          // Support for http basic authentication
00083 //          String basicAuth = fwCtx.props.getProperty("http.basicAuth");
00084 //          if (basicAuth != null && !"".equals(basicAuth)) {
00085 //            if ("http".equals(url.getProtocol()) ||
00086 //                "https".equals(url.getProtocol())) {
00087 //              String base64 = Util.base64Encode(basicAuth);
00088 //              conn.setRequestProperty("Authorization",
00089 //                                      "Basic " +base64);
00090 //            }
00091 //          }
00092 
00093           if (location.scheme() != "file")
00094           {
00095             throw std::runtime_error(std::string("Unsupported url scheme: ") + qPrintable(location.scheme()));
00096           }
00097           else
00098           {
00099             qDebug() << QString("Trying to install file:") << location.path();
00100             localPluginPath = location.toLocalFile();
00101           }
00102         } 
00103         else 
00104         {
00105           //TODO copy the QIODevice to a local cache
00106         }
00107 
00108         pa = fwCtx->storage.insertPlugin(location, localPluginPath);
00109 
00110         ctkPlugin* res = new ctkPlugin(fwCtx, pa);
00111         plugins.insert(location.toString(), res);
00112 
00113         //TODO send event
00114         //fwCtx.listeners.bundleChanged(new BundleEvent(BundleEvent.INSTALLED, b));
00115 
00116         return res;
00117       }
00118       catch (const std::exception& e)
00119       {
00120         if (pa) {
00121           pa->purge();
00122         }
00123   //      if (dynamic_cast<const SecurityException&>(e)) {
00124   //        throw;
00125   //      }
00126   //      else
00127   //      {
00128         throw ctkPluginException(QString("Failed to install plugin: ") + QString(e.what()),
00129                                 ctkPluginException::UNSPECIFIED, e);
00130   //      }
00131       }
00132     }
00133 
00134   }
00135 
00136   void ctkPlugins::remove(const QUrl& location)
00137   {
00138     QWriteLocker lock(&pluginsLock);
00139     delete plugins.take(location.toString());
00140   }
00141 
00142   ctkPlugin* ctkPlugins::getPlugin(int id) const
00143   {
00144     if (!fwCtx)
00145     { // This plugins instance has been closed!
00146       throw std::logic_error("ctkPlugins::getPlugin(id) called on closed plugins object.");
00147     }
00148 
00149     {
00150       QReadLocker lock(&pluginsLock);
00151 
00152       QHashIterator<QString, ctkPlugin*> it(plugins);
00153       while (it.hasNext())
00154       {
00155         ctkPlugin* plugin = it.next().value();
00156         if (plugin->getPluginId() == id) {
00157           return plugin;
00158         }
00159       }
00160     }
00161     return 0;
00162   }
00163 
00164   ctkPlugin* ctkPlugins::getPlugin(const QString& location) const {
00165     if (!fwCtx)
00166     { // This plugins instance has been closed!
00167       throw std::logic_error("ctkPlugins::getPlugin(location) called on closed plugins object.");
00168     }
00169 
00170     QReadLocker lock(&pluginsLock);
00171     QHash<QString, ctkPlugin*>::const_iterator it = plugins.find(location);
00172     if (it != plugins.end()) return it.value();
00173     return 0;
00174   }
00175 
00176   ctkPlugin* ctkPlugins::getPlugin(const QString& name, const ctkVersion& version) const
00177   {
00178     if (!fwCtx)
00179     { // This ctkPlugins instance has been closed!
00180       throw std::logic_error("ctkPlugins::getPlugin(name, version) called on closed plugins object.");
00181     }
00182 
00183     {
00184       QReadLocker lock(&pluginsLock);
00185 
00186       QHashIterator<QString, ctkPlugin*> it(plugins);
00187       while (it.hasNext())
00188       {
00189         ctkPlugin* plugin = it.next().value();
00190         if ((name == plugin->getSymbolicName()) && (version == plugin->getVersion()))
00191         {
00192           return plugin;
00193         }
00194       }
00195     }
00196     return 0;
00197   }
00198 
00199   QList<ctkPlugin*> ctkPlugins::getPlugins() const
00200   {
00201     if (!fwCtx)
00202     { // This plugins instance has been closed!
00203       throw std::logic_error("ctkPlugins::getPlugins() called on closed plugins object.");
00204     }
00205 
00206     {
00207       QReadLocker lock(&pluginsLock);
00208       return plugins.values();
00209     }
00210   }
00211 
00212   QList<ctkPlugin*> ctkPlugins::getPlugins(const QString& name) const
00213   {
00214     QList<ctkPlugin*> res;
00215 
00216     {
00217       QReadLocker lock(&pluginsLock);
00218       QHashIterator<QString, ctkPlugin*> it(plugins);
00219       while (it.hasNext())
00220       {
00221         ctkPlugin* plugin = it.next().value();
00222         if (name == plugin->getSymbolicName())
00223         {
00224           res.push_back(plugin);
00225         }
00226       }
00227     }
00228 
00229     return res;
00230   }
00231 
00232   QList<ctkPlugin*> ctkPlugins::getPlugins(const QString& name, const ctkVersionRange& range) const {
00233     if (!fwCtx)
00234     { // This plugins instance has been closed!
00235       throw std::logic_error("ctkPlugins::getPlugins(name, versionRange) called on closed plugins object.");
00236     }
00237 
00238     QList<ctkPlugin*> pluginsWithName = getPlugins(name);
00239     QList<ctkPlugin*> res;
00240 
00241     QListIterator<ctkPlugin*> it(pluginsWithName);
00242     while (it.hasNext()) {
00243       ctkPlugin* plugin = it.next();
00244       if (range.withinRange(plugin->getVersion()))
00245       {
00246         int j = res.size();
00247         while (--j >= 0)
00248         {
00249           if (plugin->getVersion().compare(res.at(j)->getVersion()) <= 0)
00250           {
00251             break;
00252           }
00253         }
00254         res.insert(j + 1, plugin);
00255       }
00256     }
00257 
00258     return res;
00259   }
00260 
00261   QList<ctkPlugin*> ctkPlugins::getActivePlugins() const {
00262     if (!fwCtx)
00263     { // This plugins instance has been closed!
00264       throw std::logic_error("ctkPlugins::getActivePlugins() called on closed plugins object.");
00265     }
00266 
00267     QList<ctkPlugin*> slist;
00268     {
00269       QReadLocker lock(&pluginsLock);
00270       QHashIterator<QString, ctkPlugin*> it(plugins);
00271       while (it.hasNext())
00272       {
00273         ctkPlugin* plugin = it.next().value();
00274         ctkPlugin::State s = plugin->getState();
00275         if (s == ctkPlugin::ACTIVE || s == ctkPlugin::STARTING) {
00276           slist.push_back(plugin);
00277         }
00278       }
00279     }
00280     return slist;
00281   }
00282 
00283   void ctkPlugins::load() {
00284     QList<ctkPluginArchive*> pas = fwCtx->storage.getAllPluginArchives();
00285     QListIterator<ctkPluginArchive*> it(pas);
00286 
00287     {
00288       QWriteLocker lock(&pluginsLock);
00289       while (it.hasNext())
00290       {
00291         ctkPluginArchive* pa = it.next();
00292         try
00293         {
00294           ctkPlugin* plugin = new ctkPlugin(fwCtx, pa);
00295           plugins.insert(pa->getPluginLocation().toString(), plugin);
00296         }
00297         catch (const std::exception& e)
00298         {
00299           pa->setAutostartSetting(-1); // Do not start on launch
00300           pa->setStartLevel(-2); // Mark as uninstalled
00301 
00302           std::cerr << "Error: Failed to load bundle "
00303                     << pa->getPluginId()
00304                     << " ("  << qPrintable(pa->getPluginLocation().toString())  << ")"
00305                     << " uninstalled it!\n";
00306           std::cerr << e.what();
00307         }
00308       }
00309     }
00310   }
00311 
00312   void ctkPlugins::startPlugins(const QList<ctkPlugin*>& slist) const {
00313     // Sort in start order
00314     // Resolve first to avoid dead lock
00315     QListIterator<ctkPlugin*> it(slist);
00316     while (it.hasNext())
00317     {
00318       ctkPlugin* plugin = it.next();
00319       ctkPluginPrivate* pp = plugin->d_func();
00320       pp->getUpdatedState();
00321     }
00322 
00323     it.toFront();
00324     while (it.hasNext())
00325     {
00326       ctkPlugin* plugin = it.next();
00327       ctkPluginPrivate* pp = plugin->d_func();
00328       if (pp->getUpdatedState() == ctkPlugin::RESOLVED)
00329       {
00330         try
00331         {
00332           plugin->start(0);
00333         }
00334         catch (const ctkPluginException& pe)
00335         {
00336           pp->fwCtx->listeners.frameworkError(plugin, pe);
00337         }
00338       }
00339     }
00340 
00341 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated on 21 May 2010 for CTK by  doxygen 1.6.1