void MountCommand::buildBackend (Cmdline const & cl) { MountBackendBuilder backend; Key mpk (mp, KEY_CASCADING_NAME, KEY_END); if (!mpk.isValid ()) { throw invalid_argument (mp + " is not a valid mountpoint"); } backend.setMountpoint (mpk, mountConf); backend.setBackendConfig (cl.getPluginsConfig ("system/")); PluginSpec resolver (cl.resolver); if (cl.debug) { cout << "Trying to load the resolver plugin " << resolver.getName () << endl; } backend.addPlugin (PluginSpec (resolver)); if (cl.interactive) { cout << endl; cout << "Enter a path to a file in the filesystem." << endl; cout << "The path must either not exist or be a file." << endl; cout << "For user or cascading mountpoints it must be a relative path." << endl; cout << "Then, the path will be resolved dynamically." << endl; cout << "Path: "; cin >> path; }
std::vector<PluginSpec> PluginVariantDatabase::getPluginVariantsFromSysconf (PluginSpec const & whichplugin, KeySet const & sysconf, KeySet const & genconfToIgnore) const { std::vector<PluginSpec> result; KeySet ksSysconf (sysconf); // first find possible variants Key kVariantBase ("system/elektra/plugins", KEY_END); kVariantBase.addBaseName (whichplugin.getName ()); kVariantBase.addBaseName ("variants"); KeySet ksPluginVariantSysconf (ksSysconf.cut (kVariantBase)); KeySet ksToIterate (ksPluginVariantSysconf); for (auto kCurrent : ksToIterate) { Key kCurrentTest (kVariantBase); kCurrentTest.addBaseName (kCurrent.getBaseName ()); if (kCurrentTest == kCurrent) { PluginSpec variant (whichplugin); KeySet ksVariantConfToAdd; // new base for plugin conf Key kVariantPluginConf ("system/", KEY_END); // add system conf for plugin variant Key kVariantSysconf (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "config")); this->addKeysBelowKeyToConf (kVariantSysconf, ksPluginVariantSysconf, kVariantPluginConf, ksVariantConfToAdd); // check if the variant was disabled : system/elektra/plugins/simpleini/variants/space/disable Key kDisable = sysconf.lookup (this->buildVariantSysconfKey (whichplugin, kCurrent.getBaseName (), "disable")); if (kDisable && kDisable.getString () == "1") { continue; // skip this variant } // check if the variant is in the genconfToIgnore list Key kGenconfVariant (kVariantPluginConf); kGenconfVariant.addBaseName (kCurrent.getBaseName ()); Key kIgnore = genconfToIgnore.lookup (kGenconfVariant); if (kIgnore) { continue; // this variant was added by genconf already } if (ksVariantConfToAdd.size () == 0) { continue; // no config means no variant } variant.appendConfig (ksVariantConfToAdd); result.push_back (variant); } } return result; }
Key PluginVariantDatabase::buildVariantSysconfKey (PluginSpec const & whichplugin, std::string const & variant, std::string const & attr) const { Key result ("system/elektra/plugins", KEY_END); result.addBaseName (whichplugin.getName ()); result.addBaseName ("variants"); result.addBaseName (variant); result.addBaseName (attr); return result; }
PluginDatabase::func_t ModulesPluginDatabase::getSymbol (PluginSpec const & spec, std::string const & which) const { try { PluginPtr plugin = impl->modules.load (spec.getName (), spec.getConfig ()); return plugin->getSymbol (which); } catch (...) { return NULL; } }
PluginDatabase::Status ModulesPluginDatabase::status (PluginSpec const & spec) const { PluginPtr plugin; try { KeySet conf = spec.getConfig (); conf.append (Key ("system/module", KEY_VALUE, "this plugin was loaded for the status", KEY_END)); plugin = impl->modules.load (spec.getName (), conf); return real; } catch (...) { if (hasProvides (*this, spec.getName ())) { return provides; } else { return missing; } } }
std::string ModulesPluginDatabase::lookupInfo (PluginSpec const & spec, std::string const & which) const { PluginPtr plugin; try { plugin = impl->modules.load (spec.getName (), spec.getConfig ()); } catch (...) { throw; } return plugin->lookupInfo (which); }
PluginDatabase::Status MockPluginDatabase::status (PluginSpec const & spec) const { auto it = data.find (spec); if (it != data.end ()) { return real; } if (hasProvides (*this, spec.getName ())) { return provides; } return missing; }
void PluginAdder::addPlugin (PluginSpec const & spec) { PluginPtr plugin = modules.load (spec); if (!plugin) { throw NoPlugin (spec.getName ()); } std::shared_ptr<Plugin> sharedPlugin = std::move (plugin); std::istringstream ss (sharedPlugin->lookupInfo ("placements")); std::string placement; while (ss >> placement) { if (sharedPlugin->lookupInfo ("stacking") == "" && placement == "postgetstorage") { // reverse postgetstorage, except stacking is set plugins[placement].push_front (sharedPlugin); } else { plugins[placement].push_back (sharedPlugin); } } }
bool operator() (PluginSpec const & s1, PluginSpec const & s2) const { return s1.getName () == s2.getName (); }
/** * @brief Add a plugin. * * @pre Needs to be a unique new name (use refname if you want to add the same module multiple times) * * Will automatically resolve virtual plugins to actual plugins. * * Also calls the checkconf function if provided by the plugin. The checkconf function has the * following signature: int checkconf (Key * errorKey, KeySet * config) and allows a plugin to * verify its configuration at mount time. * * @see resolveNeeds() * @param plugin */ void BackendBuilder::addPlugin (PluginSpec const & plugin) { typedef int (*checkConfPtr) (ckdb::Key *, ckdb::KeySet *); for (auto & p : toAdd) { if (p.getFullName () == plugin.getFullName ()) { throw PluginAlreadyInserted (plugin.getFullName ()); } } PluginSpec newPlugin = plugin; // if the plugin is actually a provider use it (otherwise we will get our name back): PluginSpec provides = pluginDatabase->lookupProvides (plugin.getName ()); if (provides.getName () != newPlugin.getName ()) { // keep our config and refname newPlugin.setName (provides.getName ()); newPlugin.appendConfig (provides.getConfig ()); } // call plugin's checkconf function (if provided) // this enables a plugin to verify its configuration at mount time checkConfPtr checkConfFunction = reinterpret_cast<checkConfPtr> (pluginDatabase->getSymbol (newPlugin, "checkconf")); if (checkConfFunction) { ckdb::Key * errorKey = ckdb::keyNew (0); // merge plugin config and backend config together ckdb::KeySet * pluginConfig = newPlugin.getConfig ().dup (); ckdb::ksAppend (pluginConfig, backendConf.getKeySet ()); // call the plugin's checkconf function int checkResult = checkConfFunction (errorKey, pluginConfig); if (checkResult == -1) { ckdb::ksDel (pluginConfig); throw PluginConfigInvalid (errorKey); } else if (checkResult == 1) { // separate plugin config from the backend config ckdb::Key * backendParent = ckdb::keyNew ("system/", KEY_END); ckdb::KeySet * newBackendConfig = ckdb::ksCut (pluginConfig, backendParent); // take over the new configuration KeySet modifiedPluginConfig = KeySet (pluginConfig); KeySet modifiedBackendConfig = KeySet (newBackendConfig); newPlugin.setConfig (modifiedPluginConfig); setBackendConfig (modifiedBackendConfig); ckdb::keyDel (backendParent); } else { ckdb::ksDel (pluginConfig); } ckdb::keyDel (errorKey); } toAdd.push_back (newPlugin); sort (); }
bool PluginManager::loadPlugins() { QStringList pluginSpecNameFilters; pluginSpecNameFilters.append("*.xml"); QString filename; PluginSpec *pluginSpec; bool disablePluginViewer = false; QString currentPath = QDir::current().absolutePath(); // Load plugin specs for (int i = 0; i < pluginPaths.size(); i++) { qDebug() << pluginPaths.at(i); QDir dir(pluginPaths.at(i)); dir.setNameFilters(pluginSpecNameFilters); QDirIterator dirIterator(dir, QDirIterator::Subdirectories); while (dirIterator.hasNext()) { dirIterator.next(); filename = dirIterator.fileInfo().absoluteFilePath(); pluginSpec = new PluginSpec(filename); qDebug() << "Loaded pluginspec: " << pluginSpec->getVendor() + "." + pluginSpec->getName(); pluginMap.insert(pluginSpec->getVendor() + "." + pluginSpec->getName(), pluginSpec); } } // First load the core plugin pluginSpec = pluginMap.value(corePluginName); if ( !(pluginSpec && loadPlugin(pluginSpec) ) ) { qDebug() << "could not load core plugin"; return false; } qDebug() << "read selected Plugins file: " << selectedPluginsFile; QFile selectedPlugins(selectedPluginsFile); if (!selectedPlugins.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "could not open file"; } QString pluginToLoad; QTextStream in(&selectedPlugins); pluginToLoad = in.readLine(); while (!pluginToLoad.isNull()) { qDebug() << "selectedPlugin: " << pluginToLoad; if (!pluginToLoad.startsWith('#')) { pluginConfig.insert(pluginToLoad, true); pluginSpec = pluginMap.value(pluginToLoad); if ( !(pluginSpec && loadPlugin(pluginSpec) ) ) { qDebug() << "could not load plugin: " << pluginToLoad; QDir::setCurrent(currentPath); return false; } qDebug() << pluginSpec->getCategory(); if (pluginSpec->getCategory() == "GUI") { disablePluginViewer = true; } } else pluginConfig.insert(pluginToLoad.remove("#"), false); pluginToLoad = in.readLine(); } if (!disablePluginViewer) showPluginViewer(); // reset the current path, because plugin loaders would change // it during the loading process QDir::setCurrent(currentPath); return true; }