00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __PION_CONFIGMANAGER_HEADER__
00021 #define __PION_CONFIGMANAGER_HEADER__
00022
00023 #include <string>
00024 #include <libxml/tree.h>
00025 #include <boost/noncopyable.hpp>
00026 #include <boost/lexical_cast.hpp>
00027 #include <pion/PionConfig.hpp>
00028 #include <pion/PionException.hpp>
00029 #include <pion/PionLogger.hpp>
00030 #include <pion/PionId.hpp>
00031
00032
00033 namespace pion {
00034 namespace platform {
00035
00036
00040 class PION_PLATFORM_API ConfigManager
00041 : public boost::noncopyable
00042 {
00043 public:
00044
00046 class ConfigNotOpenException : public PionException {
00047 public:
00048 ConfigNotOpenException(const std::string& config_file)
00049 : PionException("Configuration file must be opened before making changes: ", config_file) {}
00050 };
00051
00053 class ConfigAlreadyOpenException : public PionException {
00054 public:
00055 ConfigAlreadyOpenException(const std::string& file_name)
00056 : PionException("Configuration file is already open: ", file_name) {}
00057 };
00058
00060 class ConfigFileExistsException : public PionException {
00061 public:
00062 ConfigFileExistsException(const std::string& file_name)
00063 : PionException("Configuration file already exists: ", file_name) {}
00064 };
00065
00067 class MissingConfigFileException : public PionException {
00068 public:
00069 MissingConfigFileException(const std::string& file_name)
00070 : PionException("Unable to find configuration file: ", file_name) {}
00071 };
00072
00074 class MissingRootElementException : public PionException {
00075 public:
00076 MissingRootElementException(const std::string& config_file)
00077 : PionException("Configuration file is missing the root config element: ", config_file) {}
00078
00079 MissingRootElementException(const char* buffer)
00080 : PionException("Root config element not found in buffer: ", buffer) {}
00081 };
00082
00084 class MissingResourceElementException : public PionException {
00085 public:
00086 MissingResourceElementException(const std::string& resource_name)
00087 : PionException("Could not find element for specified resource: ", resource_name) {}
00088 };
00089
00091 class InitializeRootConfigException : public PionException {
00092 public:
00093 InitializeRootConfigException(const std::string& file_name)
00094 : PionException("Unable to initialize configuration file: ", file_name) {}
00095 };
00096
00098 class ConfigFileVersionException : public PionException {
00099 public:
00100 ConfigFileVersionException(const std::string& file_name)
00101 : PionException("Incompatible configuration file (run pupgrade.py): ", file_name) {}
00102 };
00103
00105 class WriteConfigException : public PionException {
00106 public:
00107 WriteConfigException(const std::string& file_name)
00108 : PionException("Unable to write config to file: ", file_name) {}
00109 };
00110
00112 class UpdateConfigException : public PionException {
00113 public:
00114 UpdateConfigException(const std::string& element_name)
00115 : PionException("Unable to update configuration. Element name: ", element_name) {}
00116 };
00117
00119 class ReadConfigException : public PionException {
00120 public:
00121 ReadConfigException(const std::string& config_file)
00122 : PionException("Unable to read config file: ", config_file) {}
00123 };
00124
00126 class BadXMLBufferException : public PionException {
00127 public:
00128 BadXMLBufferException(void)
00129 : PionException("NULL buffer pointer or buffer length is zero") {}
00130 };
00131
00133 class XMLBufferParsingException : public PionException {
00134 public:
00135 XMLBufferParsingException(const char* buffer)
00136 : PionException("Unable to parse buffer: ", buffer) {}
00137 };
00138
00140 class AddPluginConfigException : public PionException {
00141 public:
00142 AddPluginConfigException(const std::string& plugin_type)
00143 : PionException("Unable to add a plug-in to the configuration file: ", plugin_type) {}
00144 };
00145
00147 class UpdatePluginConfigException : public PionException {
00148 public:
00149 UpdatePluginConfigException(const std::string& plugin_id)
00150 : PionException("Unable to update a plug-in in the configuration file: ", plugin_id) {}
00151 };
00152
00154 class RemovePluginConfigException : public PionException {
00155 public:
00156 RemovePluginConfigException(const std::string& plugin_id)
00157 : PionException("Unable to remove a plug-in from the configuration file: ", plugin_id) {}
00158 };
00159
00161 class EmptyPluginIdException : public PionException {
00162 public:
00163 EmptyPluginIdException(const std::string& config_file)
00164 : PionException("Configuration file includes a plug-in with an empty identifier: ", config_file) {}
00165 };
00166
00168 class EmptyPluginElementException : public PionException {
00169 public:
00170 EmptyPluginElementException(const std::string& plugin_id)
00171 : PionException("Plug-in configuration does not contain a \"plugin\" element: ", plugin_id) {}
00172 };
00173
00174
00176 virtual ~ConfigManager() { closeConfigFile(); }
00177
00179 virtual void createConfigFile(void);
00180
00182 virtual void openConfigFile(void);
00183
00184 static xmlDocPtr getConfigFromFile(const std::string& config_file, const std::string& root_element_name, xmlNodePtr& config_ptr, PionLogger& logger);
00185
00187 inline void setConfigFile(const std::string& config_file) {
00188 m_config_file = config_file;
00189 resetDataDirectory();
00190 }
00191
00193 inline const std::string& getConfigFile(void) const { return m_config_file; }
00194
00196 inline bool configIsOpen(void) const { return m_config_doc_ptr != NULL; }
00197
00199 inline void setLogger(PionLogger log_ptr) { m_logger = log_ptr; }
00200
00202 inline PionLogger getLogger(void) { return m_logger; }
00203
00205 inline void setDataDirectory(const std::string& dir) { m_data_directory = dir; }
00206
00208 inline const std::string& getDataDirectory(void) const { return m_data_directory; }
00209
00211 inline void resetDataDirectory(void) {
00212 m_data_directory = resolveRelativePath(m_config_file, "./");
00213 }
00214
00216 inline void setDebugMode(bool b) { m_debug_mode = b; }
00217
00219 inline bool getDebugMode(void) const { return m_debug_mode; }
00220
00222 void removeConfigFile(void);
00223
00229 virtual void writeConfigXML(std::ostream& out) const {
00230 writeConfigXML(out, m_config_node_ptr, true);
00231 }
00232
00240 static void writeConfigXML(std::ostream& out,
00241 xmlNodePtr config_node,
00242 bool include_siblings = false);
00243
00249 static void writeConfigXMLHeader(std::ostream& out);
00250
00256 static void writeBeginPionConfigXML(std::ostream& out);
00257
00263 static void writeEndPionConfigXML(std::ostream& out);
00264
00270 static void writeBeginPionStatsXML(std::ostream& out);
00271
00277 static void writeEndPionStatsXML(std::ostream& out);
00278
00280 static std::string xml_encode(const std::string& str);
00281
00283 inline std::string createUUID(void) { return m_id_gen().to_string(); }
00284
00286 std::string createFilename(void);
00287
00295 std::string createFilename(const std::string& file_path);
00296
00304 static xmlNodePtr createPluginConfig(const std::string& plugin_type);
00305
00315 static xmlNodePtr createResourceConfig(const std::string& resource_name,
00316 const char *buf, std::size_t len);
00317
00326 static bool getNodeId(xmlNodePtr config_node, std::string& node_id);
00327
00337 static xmlNodePtr findConfigNodeByName(const std::string& element_name,
00338 xmlNodePtr starting_node);
00339
00351 static xmlNodePtr findConfigNodeByContent(const std::string& element_name,
00352 const std::string& content_value,
00353 xmlNodePtr starting_node);
00354
00367 static xmlNodePtr findConfigNodeByAttr(const std::string& element_name,
00368 const std::string& attr_name,
00369 const std::string& attr_value,
00370 xmlNodePtr starting_node);
00371
00383 static bool getConfigOption(const std::string& option_name,
00384 std::string& option_value,
00385 const xmlNodePtr starting_node);
00386
00387
00400 static bool getConfigOptionEmptyOk(const std::string& option_name,
00401 std::string& option_value,
00402 const xmlNodePtr starting_node);
00403
00411 static std::string getAttribute(const char *name, const xmlNodePtr ptr);
00412
00420 static std::string getAttribute(const std::string& name, const xmlNodePtr ptr)
00421 {
00422 return getAttribute(name.c_str(), ptr);
00423 }
00424
00436 template <typename ValueType>
00437 static bool getConfigOption(const std::string& option_name,
00438 ValueType& option_value,
00439 const xmlNodePtr starting_node)
00440 {
00441 std::string value_str;
00442 if (getConfigOption(option_name, value_str, starting_node)) {
00443 option_value = boost::lexical_cast<ValueType>(value_str);
00444 return true;
00445 }
00446 return false;
00447 }
00448
00461 template <typename ValueType>
00462 static bool getConfigOption(const std::string& option_name,
00463 ValueType& option_value,
00464 const ValueType& default_value,
00465 const xmlNodePtr starting_node)
00466 {
00467 if (getConfigOption(option_name, option_value, starting_node))
00468 return true;
00469 option_value = default_value;
00470 return false;
00471 }
00472
00484 static bool updateConfigOption(const std::string& option_name,
00485 const std::string& option_value,
00486 xmlNodePtr parent_node);
00487
00496 static std::string resolveRelativePath(const std::string& base_path_to_file,
00497 const std::string& orig_path);
00498
00506 inline std::string resolveRelativePath(const std::string& orig_path) const {
00507 return resolveRelativePath(getConfigFile(), orig_path);
00508 }
00509
00517 std::string resolveRelativeDataPath(const std::string& orig_path);
00518
00528 virtual bool creationAllowed(xmlNodePtr permission_config_ptr, xmlNodePtr config_ptr) const {
00529
00530 return permission_config_ptr != NULL;
00531 }
00532
00543 virtual bool updateAllowed(xmlNodePtr permission_config_ptr, const std::string& id, xmlNodePtr config_ptr) const {
00544
00545 return permission_config_ptr != NULL;
00546 }
00547
00556 virtual bool removalAllowed(xmlNodePtr permission_config_ptr, const std::string& id) const {
00557
00558 return permission_config_ptr != NULL;
00559 }
00560
00569 virtual bool accessAllowed(xmlNodePtr permission_config_ptr, const std::string& plugin_id) const {
00570
00571 return permission_config_ptr != NULL;
00572 }
00573
00575 virtual std::string getPermissionType(void) const {
00576
00577
00578
00579 return "";
00580 }
00581
00582
00583 protected:
00584
00590 ConfigManager(const std::string& default_config_file)
00591 : m_logger(PION_GET_LOGGER("pion.platform.ConfigManager")),
00592 m_config_file(default_config_file), m_debug_mode(false),
00593 m_config_doc_ptr(NULL), m_config_node_ptr(NULL)
00594 {
00595 resetDataDirectory();
00596 }
00597
00599 void closeConfigFile(void);
00600
00602 void saveConfigFile(void);
00603
00605 void backupConfigFile(void);
00606
00613 void openPluginConfig(const std::string& plugin_name);
00614
00623 bool setPluginConfig(xmlNodePtr plugin_node_ptr, xmlNodePtr config_ptr);
00624
00633 void setPluginConfig(const std::string& plugin_name,
00634 const std::string& plugin_id,
00635 const xmlNodePtr config_ptr);
00636
00647 void addPluginConfig(const std::string& plugin_name,
00648 const std::string& plugin_id,
00649 const std::string& plugin_type,
00650 const xmlNodePtr config_ptr = NULL);
00651
00658 void removePluginConfig(const std::string& plugin_name,
00659 const std::string& plugin_id);
00660
00672 virtual void addPluginNoLock(const std::string& plugin_id,
00673 const std::string& plugin_name,
00674 const xmlNodePtr config_ptr) {}
00675
00676
00678 static const std::string XML_FILE_EXTENSION;
00679
00681 static const std::string BACKUP_FILE_EXTENSION;
00682
00684 static const std::string CONFIG_NAMESPACE_URL;
00685
00687 static const std::string ROOT_ELEMENT_NAME;
00688
00690 static const std::string STATS_ELEMENT_NAME;
00691
00693 static const std::string PLUGIN_ELEMENT_NAME;
00694
00696 static const std::string NAME_ELEMENT_NAME;
00697
00699 static const std::string COMMENT_ELEMENT_NAME;
00700
00702 static const std::string PION_VERSION_ATTRIBUTE_NAME;
00703
00705 static const std::string ID_ATTRIBUTE_NAME;
00706
00707
00709 PionLogger m_logger;
00710
00712 PionIdGenerator m_id_gen;
00713
00715 std::string m_config_file;
00716
00718 std::string m_data_directory;
00719
00721 bool m_debug_mode;
00722
00724 xmlDocPtr m_config_doc_ptr;
00725
00727 xmlNodePtr m_config_node_ptr;
00728 };
00729
00730
00731 }
00732 }
00733
00734 #endif