Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief Interface to all plugins
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : *
8 : */
9 :
10 :
11 : #ifndef TOOLS_PLUGIN_DATABASE_HPP
12 : #define TOOLS_PLUGIN_DATABASE_HPP
13 :
14 : #include <map>
15 : #include <memory>
16 : #include <unordered_map>
17 :
18 : #include <kdb.hpp>
19 :
20 : #include <pluginspec.hpp>
21 :
22 : namespace kdb
23 : {
24 :
25 : namespace tools
26 : {
27 :
28 : /**
29 : * @brief Loads all plugins and allows us to query them.
30 : */
31 : class PluginDatabase
32 : {
33 : protected:
34 : typedef void (*func_t) ();
35 :
36 : public:
37 : /* TODO: reintroduce with next API break
38 : virtual ~PluginDatabase ()
39 : {
40 : }
41 : */
42 :
43 : /**
44 : * @brief list all plugins
45 : *
46 : * If Elektra is compiled with plugins, it will search for shared libraries.
47 : * In any case, if no shared libraries were found
48 : * it will fallback to an internal list (plugins that were compiled together with Elektra).
49 : *
50 : * @return a list of all available plugins
51 : */
52 : virtual std::vector<std::string> listAllPlugins () const = 0;
53 :
54 : // TODO: add additional functions:
55 : // virtual void registerPlugin(PluginSpec) = 0;
56 : // virtual std::vector<PluginSpec> listAllPlugins() const = 0;
57 :
58 : enum Status
59 : {
60 : /// does not directly, but can be loaded via provides
61 : provides,
62 : /// exists and working as given
63 : real,
64 : /// does not exist or cannot be loaded
65 : missing
66 : };
67 :
68 : virtual Status status (PluginSpec const & whichplugin) const = 0;
69 :
70 : /**
71 : * @brief lookup contract clauses or dynamic information
72 : *
73 : * @param whichplugin about which plugin?
74 : * @param which about which clause in the contract?
75 : *
76 : * @return the clause of the contract
77 : */
78 : virtual std::string lookupInfo (PluginSpec const & whichplugin, std::string const & which) const = 0;
79 :
80 : /**
81 : * @brief get exported plugin symbol
82 : *
83 : * @param whichplugin from which plugin?
84 : * @param which which symbol would you like to look up?
85 : *
86 : * @return the function pointer to the exported symbol or NULL if the symbol was not found
87 : */
88 : virtual func_t getSymbol (PluginSpec const & whichplugin, std::string const & which) const = 0;
89 :
90 : /**
91 : * @brief lookup which plugin handles metadata
92 : *
93 : * @param which the metadata of interest
94 : *
95 : * @return the best suited plugin specification which provides it
96 : */
97 : virtual PluginSpec lookupMetadata (std::string const & which) const = 0;
98 :
99 : /**
100 : * @brief lookup which plugin is a provider for that plugin
101 : *
102 : * @note will return a PluginSpec with getName() == provides if the string provides
103 : * actually is a plugin name.
104 : *
105 : * @param provides is the provider to find
106 : *
107 : * @throw NoPlugin if no plugin that provides the functionality could be found
108 : *
109 : * @return the plugin itself or the best suited plugin specification which provides it
110 : */
111 : virtual PluginSpec lookupProvides (std::string const & provides) const = 0;
112 :
113 : /**
114 : * @brief looks up all plugins which are a suitable provider
115 : *
116 : * @note in case a plugin name is provided, the plugin with the name will also be
117 : * part of the result. But if there are other plugins providing the requirement,
118 : * then they will also be part of the result.
119 : *
120 : * @param provides is the provider to find
121 : *
122 : * @return a map of plugins with their status offering the requirement or are named after it
123 : */
124 : virtual std::map<int, PluginSpec> lookupAllProvidesWithStatus (std::string const & provides) const = 0;
125 :
126 : /**
127 : * @brief looks up all plugins which are a suitable provider
128 : *
129 : * @note in case a plugin name is provided, the plugin with the name will also be
130 : * part of the result. But if there are other plugins providing the requirement,
131 : * then they will also be part of the result.
132 : * The ordering of the resulting vector has no special meaning.
133 : *
134 : * @param provides is the provider to find
135 : *
136 : * @return a vector of plugins offering the requirement or are named after it
137 : */
138 : virtual std::vector<PluginSpec> lookupAllProvides (std::string const & provides) const = 0;
139 :
140 : /**
141 : * @param statusString the string encoding the status
142 : *
143 : * @return The representing number for a given status.
144 : */
145 : static int calculateStatus (std::string statusString);
146 :
147 : static const std::map<std::string, int> statusMap;
148 : };
149 :
150 : typedef std::shared_ptr<PluginDatabase> PluginDatabasePtr;
151 :
152 : /**
153 : * @brief A plugin database that works with installed modules
154 : */
155 : class ModulesPluginDatabase : public PluginDatabase
156 : {
157 : protected:
158 : class Impl;
159 : std::unique_ptr<Impl> impl;
160 :
161 : public:
162 : ModulesPluginDatabase ();
163 : ~ModulesPluginDatabase ();
164 : /* TODO: reintroduce with next API break
165 : virtual ~ModulesPluginDatabase ();
166 : */
167 :
168 : std::vector<std::string> listAllPlugins () const;
169 : PluginDatabase::Status status (PluginSpec const & whichplugin) const;
170 : std::string lookupInfo (PluginSpec const & spec, std::string const & which) const;
171 : func_t getSymbol (PluginSpec const & whichplugin, std::string const & which) const;
172 : PluginSpec lookupMetadata (std::string const & which) const;
173 : PluginSpec lookupProvides (std::string const & provides) const;
174 : std::map<int, PluginSpec> lookupAllProvidesWithStatus (std::string const & provides) const;
175 : std::vector<PluginSpec> lookupAllProvides (std::string const & provides) const;
176 : };
177 :
178 : class PluginVariantDatabase : public ModulesPluginDatabase
179 : {
180 : class VariantImpl;
181 : std::unique_ptr<VariantImpl> variantImpl;
182 :
183 : public:
184 : /**
185 : * @brief constructor that takes a configuration keyset for plugins
186 : *
187 : * takes the list of plugins provided by the ModulesPluginDatabase and
188 : * removes all plugins that are disabled in the system config which was
189 : * given to the constructor.
190 : *
191 : * example: removes the `simpleini` plugin if an entry like
192 : *
193 : * system/elektra/plugins/simpleini/disable = 1
194 : *
195 : * exists in the keyset handed to the constructor
196 : *
197 : * @note the constructor should be called with a keyset containing
198 : * the keys for system/elektra/plugins
199 : *
200 : * @param conf keyset containing keys from system/elektra/plugins
201 : */
202 : explicit PluginVariantDatabase (const KeySet & conf);
203 : ~PluginVariantDatabase ();
204 : /* TODO: reintroduce with next API break
205 : virtual ~PluginVariantDatabase ();
206 : */
207 :
208 : std::vector<std::string> listAllPlugins () const;
209 :
210 : /**
211 : * @brief returns a list of plugin variants for the plugin
212 : *
213 : * takes the genconf function provided by plugins to generate variants.
214 : * variants can be disabled through the system configuration handed to
215 : * the constructor of the class.
216 : *
217 : * example: ignores a variant `spacesep` delivered by genconf if an entry like
218 : *
219 : * system/elektra/plugins/simpleini/variants/spacesep/disable = 1
220 : *
221 : * exists in the keyset handed to the constructor
222 : *
223 : * @note if no plugin variant could be found, an empty vector will be returned.
224 : *
225 : * @param whichplugin is the plugin for which we want all variants
226 : *
227 : * @return a vector of plugin variants for the given plugin
228 : */
229 : std::vector<PluginSpec> getPluginVariants (PluginSpec const & whichplugin) const;
230 :
231 : private:
232 : /**
233 : * @brief returns a list of plugin variants created from the system config
234 : *
235 : * considered are keys below system/elektra/plugins/<plugin>/variants
236 : *
237 : * @note variants listed in @p genconfToIgnore are not added to the result.
238 : * it is expected that they were added at another point already
239 : * (e.g. explicit override check).
240 : *
241 : * @param whichplugin is the plugin for which we want all variants
242 : * @param sysconf is a keyset containing the system config for system/elektra/plugins
243 : * @param genconfToIgnore is a keyset containing variants to ignore from the sysconf
244 : *
245 : * @return a vector of pluginspecs with variant configurations
246 : */
247 : std::vector<PluginSpec> getPluginVariantsFromSysconf (PluginSpec const & whichplugin, KeySet const & sysconf,
248 : KeySet const & genconfToIgnore) const;
249 :
250 : /**
251 : * @brief returns a list of plugin variants created from the genconf config
252 : *
253 : * does take a keyset with config from the `genconf` plugin function, but also
254 : * an additional @p sysconf keyset with config from system/elektra/plugins to
255 : * ensure overrides and disabled variants.
256 : *
257 : * the function does also add all variants from @p sysconf that were not mentioned
258 : * in @p genconf yet.
259 : *
260 : * @param whichplugin is the plugin for which we want all variants
261 : * @param genconf is a keyset containing the genconf config from the plugin
262 : * @param sysconf is a keyset containing the system config for system/elektra/plugins
263 : *
264 : * @return a vector of pluginspecs with variant configurations
265 : */
266 : std::vector<PluginSpec> getPluginVariantsFromGenconf (PluginSpec const & whichplugin, KeySet const & genconf,
267 : KeySet const & sysconf) const;
268 :
269 : /**
270 : * @brief builds a sysconf key from several inputs
271 : *
272 : * builds a key like:
273 : *
274 : * system/elektra/plugin/<whichplugin>/variants/<variant>/<attr>
275 : *
276 : * @note the function does not add a value and it does not lookup the key in any
277 : * keyset, it just creates the key by adding every part as basename.
278 : *
279 : * @param whichplugin is the plugin for which we want a key
280 : * @param variant is the plugin variant for which we want a key
281 : * @param attr is the attribute of a variant for which we want a key, e.g. info or config
282 : *
283 : * @return a newly created key matching the inputs which can be used for lookups for example
284 : */
285 : Key buildVariantSysconfKey (PluginSpec const & whichplugin, std::string const & variant, const std::string attr) const;
286 :
287 : /**
288 : * @brief adds all keys of a keyset below a certain key to another keyset, rebased
289 : *
290 : * lets take the input keyset (@p conf):
291 : *
292 : * system/elektra/plugins/simpleini/variants/spacesep
293 : * system/elektra/plugins/simpleini/variants/spacesep/config
294 : * system/elektra/plugins/simpleini/variants/spacesep/config/format = % %
295 : * system/elektra/plugins/simpleini/variants/spacesep/config/ignorewhitespace = 1
296 : *
297 : * and the input key (@p below):
298 : *
299 : * system/elektra/plugins/simpleini/variants/spacesep/config
300 : *
301 : * and the new base key (@p newbase):
302 : *
303 : * system/
304 : *
305 : * then we get the following keys in the output keyset (@p targetconf):
306 : *
307 : * system/format = % %
308 : * system/ignorewhitespace = 1
309 : *
310 : * @param below the parent key for everything we want to add to the target keyset
311 : * @param conf the keyset of which we want to add the keys to the target keyset
312 : * @param newbase the new base key used in the rebasing process
313 : * @param targetconf the target keyset to use for the transformation
314 : */
315 : void addKeysBelowKeyToConf (Key const & below, KeySet const & conf, Key const & newbase, KeySet & targetconf) const;
316 : };
317 :
318 : /**
319 : * @brief A plugin database that works with added fake data
320 : */
321 328 : class MockPluginDatabase : public ModulesPluginDatabase
322 : {
323 : public:
324 : typedef int (*checkConfPtr) (ckdb::Key *, ckdb::KeySet *);
325 :
326 : /// only data from here will be returned
327 : /// @note that it is ordered by name, i.e., different ref-names cannot be distinguished
328 : mutable std::unordered_map<PluginSpec, std::unordered_map<std::string, std::string>, PluginSpecHash, PluginSpecName> data;
329 :
330 : std::vector<std::string> listAllPlugins () const;
331 : PluginDatabase::Status status (PluginSpec const & whichplugin) const;
332 : std::string lookupInfo (PluginSpec const & spec, std::string const & which) const;
333 : func_t getSymbol (PluginSpec const & whichplugin, std::string const & which) const;
334 : void setCheckconfFunction (checkConfPtr const newCheckconf);
335 :
336 : private:
337 : checkConfPtr checkconf = NULL;
338 : };
339 :
340 :
341 : typedef std::shared_ptr<PluginDatabase> PluginDatabasePtr;
342 : } // namespace tools
343 : } // namespace kdb
344 :
345 : #endif
|