00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __PION_PLUGINCONFIG_HEADER__
00021 #define __PION_PLUGINCONFIG_HEADER__
00022
00023 #include <libxml/tree.h>
00024 #include <boost/bind.hpp>
00025 #include <boost/signal.hpp>
00026 #include <boost/thread/mutex.hpp>
00027 #include <pion/PionConfig.hpp>
00028 #include <pion/PionException.hpp>
00029 #include <pion/PluginManager.hpp>
00030 #include <pion/platform/Vocabulary.hpp>
00031 #include <pion/platform/VocabularyManager.hpp>
00032 #include <pion/platform/ConfigManager.hpp>
00033
00034
00035 namespace pion {
00036 namespace platform {
00037
00041 template <typename PluginType>
00042 class PluginConfig :
00043 public ConfigManager
00044 {
00045 public:
00046
00048 class PluginException : public PionException {
00049 public:
00050 PluginException(const std::string& error_msg)
00051 : PionException(error_msg)
00052 {}
00053 };
00054
00055
00057 virtual ~PluginConfig() {}
00058
00060 virtual void createConfigFile(void) {
00061 boost::mutex::scoped_lock plugins_lock(m_mutex);
00062
00063 if (ConfigManager::configIsOpen())
00064 return;
00065
00066 ConfigManager::createConfigFile();
00067 PION_LOG_INFO(m_logger, "Initializing new " << m_plugin_element
00068 << " configuration file: " << ConfigManager::getConfigFile());
00069 }
00070
00072 virtual void openConfigFile(void) {
00073 boost::mutex::scoped_lock plugins_lock(m_mutex);
00074
00075 if (ConfigManager::configIsOpen())
00076 return;
00077
00078 ConfigManager::openPluginConfig(m_plugin_element);
00079 PION_LOG_INFO(m_logger, "Loaded " << m_plugin_element
00080 << " configuration file: " << ConfigManager::getConfigFile());
00081 }
00082
00088 virtual void writeConfigXML(std::ostream& out) const {
00089 boost::mutex::scoped_lock plugins_lock(m_mutex);
00090 ConfigManager::writeConfigXMLHeader(out);
00091 ConfigManager::writeConfigXML(out, m_config_node_ptr, true);
00092 }
00093
00100 inline bool writeConfigXML(std::ostream& out, const std::string& plugin_id) const;
00101
00112 inline xmlNodePtr getPluginConfig(const std::string& plugin_id);
00113
00119 inline bool hasPlugin(const std::string& plugin_id) const {
00120 return (m_plugins.get(plugin_id) != NULL);
00121 }
00122
00129 template <typename PluginUpdateFunction>
00130 inline boost::signals::connection registerForUpdates(PluginUpdateFunction f) const {
00131 boost::mutex::scoped_lock signal_lock(m_signal_mutex);
00132 return m_signal_plugins_updated.connect(f);
00133 }
00134
00136 inline void updateVocabulary(void) {
00137 VocabularyPtr vocab_ptr(m_vocab_mgr.getVocabulary());
00138 m_plugins.run(boost::bind(&PluginType::updateVocabulary, _1,
00139 boost::cref(*vocab_ptr)));
00140 }
00141
00143 inline VocabularyPtr getVocabulary(void) const { return m_vocab_mgr.getVocabulary(); }
00144
00146 inline const VocabularyManager& getVocabularyManager(void) const { return m_vocab_mgr; }
00147
00148
00149 protected:
00150
00152 inline void releasePlugins(void) { m_plugins.clear(); }
00153
00161 PluginConfig(const VocabularyManager& vocab_mgr,
00162 const std::string& config_file,
00163 const std::string& plugin_element)
00164 : ConfigManager(config_file),
00165 m_vocab_mgr(vocab_mgr),
00166 m_plugin_element(plugin_element)
00167 {
00168 m_vocab_connection = vocab_mgr.registerForUpdates(boost::bind(&PluginConfig::updateVocabulary, this));
00169 setLogger(PION_GET_LOGGER("pion.platform.PluginConfig"));
00170 }
00171
00179 inline void setPluginConfig(const std::string& plugin_id,
00180 const xmlNodePtr config_ptr);
00181
00190 inline std::string addPlugin(const xmlNodePtr config_ptr);
00191
00197 inline void removePlugin(const std::string& plugin_id);
00198
00210 virtual void addPluginNoLock(const std::string& plugin_id,
00211 const std::string& plugin_name,
00212 const xmlNodePtr config_ptr) = 0;
00213
00214
00216 const VocabularyManager& m_vocab_mgr;
00217
00219 const std::string m_plugin_element;
00220
00222 PluginManager<PluginType> m_plugins;
00223
00225 boost::signals::scoped_connection m_vocab_connection;
00226
00228 mutable boost::signal0<void> m_signal_plugins_updated;
00229
00231 mutable boost::mutex m_signal_mutex;
00232
00234 mutable boost::mutex m_mutex;
00235 };
00236
00237
00238
00239
00240 template <typename PluginType>
00241 inline bool PluginConfig<PluginType>::writeConfigXML(std::ostream& out,
00242 const std::string& plugin_id) const
00243 {
00244
00245 boost::mutex::scoped_lock plugins_lock(m_mutex);
00246 xmlNodePtr plugin_node = findConfigNodeByAttr(m_plugin_element,
00247 ID_ATTRIBUTE_NAME,
00248 plugin_id,
00249 m_config_node_ptr->children);
00250 if (plugin_node == NULL)
00251 return false;
00252
00253
00254 ConfigManager::writeBeginPionConfigXML(out);
00255 ConfigManager::writeConfigXML(out, plugin_node, false);
00256 ConfigManager::writeEndPionConfigXML(out);
00257
00258 return true;
00259 }
00260
00261 template <typename PluginType>
00262 inline xmlNodePtr PluginConfig<PluginType>::getPluginConfig(const std::string& plugin_id)
00263 {
00264
00265 boost::mutex::scoped_lock plugins_lock(m_mutex);
00266 xmlNodePtr plugin_node = findConfigNodeByAttr(m_plugin_element,
00267 ID_ATTRIBUTE_NAME,
00268 plugin_id,
00269 m_config_node_ptr->children);
00270 if (plugin_node == NULL)
00271 throw typename PluginManager<PluginType>::PluginNotFoundException(plugin_id);
00272
00273
00274 return xmlCopyNodeList(plugin_node);
00275 }
00276
00277 template <typename PluginType>
00278 inline void PluginConfig<PluginType>::setPluginConfig(const std::string& plugin_id,
00279 const xmlNodePtr config_ptr)
00280 {
00281
00282 if (! configIsOpen())
00283 throw ConfigNotOpenException(getConfigFile());
00284
00285 VocabularyPtr vocab_ptr(m_vocab_mgr.getVocabulary());
00286
00287
00288 boost::mutex::scoped_lock plugins_lock(m_mutex);
00289 m_plugins.run(plugin_id, boost::bind(&PluginType::setConfig, _1,
00290 boost::cref(*vocab_ptr), config_ptr));
00291 ConfigManager::setPluginConfig(m_plugin_element, plugin_id, config_ptr);
00292
00293
00294 plugins_lock.unlock();
00295
00296
00297 PION_LOG_DEBUG(m_logger, "Updated " << m_plugin_element << " configuration (" << plugin_id << ')');
00298 boost::mutex::scoped_lock signal_lock(m_signal_mutex);
00299 m_signal_plugins_updated();
00300 }
00301
00302 template <typename PluginType>
00303 inline std::string PluginConfig<PluginType>::addPlugin(const xmlNodePtr config_ptr)
00304 {
00305
00306 if (! configIsOpen())
00307 throw ConfigNotOpenException(getConfigFile());
00308
00309
00310 std::string plugin_type;
00311 const std::string plugin_id(ConfigManager::createUUID());
00312 if (config_ptr == NULL || ! getConfigOption(PLUGIN_ELEMENT_NAME, plugin_type, config_ptr))
00313 throw EmptyPluginElementException(plugin_id);
00314
00315
00316 boost::mutex::scoped_lock plugins_lock(m_mutex);
00317 addPluginNoLock(plugin_id, plugin_type, config_ptr);
00318 addPluginConfig(m_plugin_element, plugin_id, plugin_type, config_ptr);
00319
00320
00321 plugins_lock.unlock();
00322
00323
00324 PION_LOG_DEBUG(m_logger, "Loaded " << m_plugin_element << " (" << plugin_type << "): " << plugin_id);
00325 boost::mutex::scoped_lock signal_lock(m_signal_mutex);
00326 m_signal_plugins_updated();
00327 signal_lock.unlock();
00328
00329
00330 return plugin_id;
00331 }
00332
00333 template <typename PluginType>
00334 inline void PluginConfig<PluginType>::removePlugin(const std::string& plugin_id)
00335 {
00336
00337 if (! configIsOpen())
00338 throw ConfigNotOpenException(getConfigFile());
00339
00340
00341
00342
00343 boost::mutex::scoped_lock plugins_lock(m_mutex);
00344 PionPluginPtr<PluginType> plugin_lib_ptr(m_plugins.getLibPtr(plugin_id));
00345
00346
00347 m_plugins.remove(plugin_id);
00348 removePluginConfig(m_plugin_element, plugin_id);
00349
00350
00351 plugins_lock.unlock();
00352
00353
00354 PION_LOG_DEBUG(m_logger, "Removed " << m_plugin_element << ": " << plugin_id);
00355 boost::mutex::scoped_lock signal_lock(m_signal_mutex);
00356 m_signal_plugins_updated();
00357 }
00358
00359
00360 }
00361 }
00362
00363 #endif