00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00030 #include <s3fc/s3_macros.h>
00031 #include <s3fc/s3_xml_config.h>
00032 #include <s3fc/s3_exception.h>
00033 #include <fstream>
00034 #include <iostream>
00035
00036
00037 s3_xml_exception::s3_xml_exception(const std::string& errstr):
00038 s3_exception(errstr)
00039 {
00040 }
00041
00042
00043
00044
00045 s3_xml_config::s3_xml_config(const std::string& n_config_file,
00046 bool create_file) throw (s3_generic_exception):
00047 config_file(n_config_file),
00048 rootnode(0)
00049 {
00050 S3FC_DBG( std::cerr << "s3_xml_config::s3_xml_config(const string&"
00051 "n_config_file) " << std::endl);
00052 if ( create_file )
00053 {
00054
00055 try
00056 {
00057 std::ofstream a_file( config_file.c_str(), std::ios::out );
00058 a_file.close();
00059 }
00060 catch (const std::exception& e)
00061 {
00062 throw s3_generic_exception("s3_xml_config::s3_xml_config Could not create file", e.what() );
00063 }
00064 }
00065
00066
00067 try
00068 {
00069 XMLPlatformUtils::Initialize();
00070 }
00071 catch(const XMLException& toCatch)
00072 {
00073 throw s3_generic_exception("s3_xml_config(const string&)",
00074 domstr_to_string(toCatch.getMessage()));
00075 }
00076 refresh();
00077 }
00078
00079
00080
00081
00082 s3_xml_config::~s3_xml_config()
00083 {
00084 S3FC_DBG( std::cerr << "s3_xml_config::~s3_xml_config" << std::endl);
00085
00086
00087 delete rootnode;
00088 rootnode = 0;
00089
00090
00091 try
00092 {
00093 XMLPlatformUtils::Terminate();
00094 }
00095 catch(const XMLException& toCatch)
00096 {
00097 throw s3_generic_exception("s3_xml_config()",
00098 domstr_to_string(toCatch.getMessage()));
00099 }
00100 }
00101
00102
00103 s3_config_node& s3_xml_config::get_rootnode() const
00104 {
00105 return *rootnode;
00106 }
00107
00108 void s3_xml_config::refresh()
00109 {
00110
00111 DOM_Document doc = parse(config_file);
00112 #ifdef DEBUG
00113
00114 dump_tree(doc);
00115 #endif
00116
00117 rootnode = build_tree(doc);
00118 }
00119
00120 void s3_xml_config::set_config_file(const std::string& n_config_file)
00121 {
00122 config_file = n_config_file;
00123 }
00124
00125
00126 void s3_xml_config::write_node(const std::string& filename,
00127 const s3_config_node& node)
00128 {
00129 std::ofstream fs(filename.c_str(), std::ios::out | std::ios::trunc);
00130 write_node(fs, node, 0);
00131 fs.close();
00132 }
00133
00134
00135 void s3_xml_config::write_node(std::ostream& os,
00136 const s3_config_node& node,
00137 unsigned int depth)
00138 {
00139 static const int tab_size = 5;
00140 write_spaces(os, depth*tab_size);
00141 os << "<" << node.get_name();
00142 for (std::map<std::string,std::string>::const_iterator ptr =
00143 node.get_attributes().begin();
00144 ptr != node.get_attributes().end();
00145 ptr++)
00146 {
00147 os << " " << ptr->first << "=\"" << ptr->second << "\"";
00148 }
00149 os << ">" << std::endl;
00150 if ( node.get_value().length() )
00151 {
00152 write_spaces(os, (depth+1)*tab_size);
00153 os << node.get_value();
00154 os << std::endl;
00155 }
00156 for (unsigned int i = 0; i < node.get_num_children(); i++)
00157 {
00158 write_node(os, node.get_child(i), depth+1);
00159 }
00160 write_spaces(os, depth*tab_size);
00161 os << "</" << node.get_name() << ">" << std::endl;
00162 }
00163
00164
00165 void s3_xml_config::write_spaces(std::ostream& os, unsigned int n)
00166 {
00167 for ( unsigned int i = 0; i < n; i++ )
00168 {
00169 os << " ";
00170 }
00171 }
00172
00173
00174
00175
00176 DOM_Document s3_xml_config::parse(const std::string& filename)
00177 throw (s3_generic_exception, s3_xml_exception)
00178 {
00179 DOMParser parser;
00180
00181
00182 s3_xml_config::error_handler err_handler;
00183 try
00184 {
00185 parser.setErrorHandler(&err_handler);
00186 parser.setValidationScheme(DOMParser::Val_Auto);
00187 parser.setDoNamespaces(false);
00188 parser.setExitOnFirstFatalError(true);
00189 parser.parse( filename.c_str() );
00190 }
00191
00192 catch (const s3_xml_exception& e)
00193 {
00194 throw e;
00195 }
00196
00197 catch (const XMLException& e)
00198 {
00199 throw s3_generic_exception("s3_xml_config::parse() "
00200 "caught XMLException",
00201 domstr_to_string(e.getMessage()));
00202 }
00203 catch (const DOM_DOMException& e)
00204 {
00205 throw s3_generic_exception("s3_xml_config::parse() "
00206 "caught DOM_DOMException",
00207 domstr_to_string(e.msg));
00208 }
00209 catch (const SAXParseException& e)
00210 {
00211
00212
00213
00214 std::stringstream ss;
00215 ss << "s3_xml_config::parse():"
00216 << " caught SAXParseException: ";
00217 ss << "" << domstr_to_string(e.getMessage()) << "";
00218 ss << " in file ";
00219 if ( e.getSystemId() )
00220 {
00221 ss << "'" << domstr_to_string(e.getSystemId()) << "'";
00222 }
00223 else
00224 {
00225 ss << "<unknown>";
00226 }
00227 ss << " line " << e.getLineNumber() << ", column "
00228 << e.getColumnNumber();
00229 std::cerr << ss.str() << std::endl << std::flush;
00230 }
00231
00232 catch (...)
00233 {
00234 throw s3_generic_exception("s3_xml_config::parse(): ",
00235 "An unkown parsing error occured");
00236 }
00237 DOM_Document doc = parser.getDocument();
00238 return doc;
00239 }
00240
00245 s3_config_node* s3_xml_config::build_tree(const DOM_Node& node)
00246 {
00247
00248
00249 std::string name = get_name(node);
00250 std::string value = get_value(node);
00251 std::map<std::string, std::string> attributes = get_attributes(node);
00252 std::vector<s3_config_node*> c = get_children(node);
00253
00254 std::vector<s3_config_node> children;
00255 for (std::vector<s3_config_node*>::iterator it = c.begin();
00256 it != c.end();
00257 ++it)
00258 {
00259 children.push_back(**it);
00260 }
00261 return new s3_config_node(name,
00262 value,
00263 0,
00264 attributes,
00265 children);
00266 }
00267
00268
00269 std::string s3_xml_config::get_name(const DOM_Node& node)
00270 {
00271 return domstr_to_string(node.getNodeName());
00272 }
00273
00274
00275
00276 std::string s3_xml_config::get_value(const DOM_Node& node)
00277 {
00278 DOM_NodeList dlst = node.getChildNodes();
00279 std::string val;
00280 for (unsigned int i = 0; i < dlst.getLength(); i++)
00281 {
00282 if (dlst.item(i).getNodeType() == DOM_Node::TEXT_NODE)
00283 {
00284 std::string tmpval = domstr_to_string(dlst.item(i).getNodeValue());
00285
00286 int strt_i = tmpval.find_first_not_of(" \t\n\r");
00287 int end_i = tmpval.find_last_not_of(" \t\n\r");
00288 if ( strt_i != -1 )
00289 {
00290 if ( val.length() )
00291 {
00292 val += " ";
00293 val += tmpval.substr(strt_i, end_i-strt_i+1);
00294 }
00295 else
00296 {
00297 val = tmpval.substr(strt_i, end_i-strt_i+1);
00298 }
00299 }
00300 }
00301 }
00302 return val;
00303
00304 }
00305
00306
00307
00308 std::map<std::string, std::string> s3_xml_config::get_attributes(
00309 const DOM_Node& node)
00310 {
00311 std::map<std::string, std::string> m;
00312 DOM_NamedNodeMap attrs = node.getAttributes();
00313 if ( attrs != 0 )
00314 {
00315 for ( unsigned int i = 0; i < attrs.getLength(); i++ )
00316 {
00317 DOM_Node n = attrs.item(i);
00318 std::string name = domstr_to_string(n.getNodeName());
00319 std::string value = domstr_to_string(n.getNodeValue());
00320 m[name] = value;
00321 }
00322 }
00323 return m;
00324 }
00325
00326
00327
00328
00329 std::vector<s3_config_node*> s3_xml_config::get_children(const DOM_Node& node)
00330 {
00331
00332 DOM_NodeList dlst = node.getChildNodes();
00333 std::vector<s3_config_node*> lst;
00334 for (unsigned int i = 0; i < dlst.getLength(); i++)
00335 {
00336 if (dlst.item(i).getNodeType() == DOM_Node::ELEMENT_NODE)
00337 {
00338 lst.push_back( build_tree(dlst.item(i)) );
00339 }
00340 }
00341 return lst;
00342 }
00343
00344
00345
00346 std::string s3_xml_config::domstr_to_string(const DOMString& dstr)
00347 {
00348 const char* c = dstr.transcode();
00349 std::string str(c);
00350
00351 #ifndef _WIN32 // Might leak.
00352 delete c;
00353 #endif
00354 return str;
00355 }
00356
00357 #ifdef DEBUG
00358
00359 void s3_xml_config::dump_DOM_tree(const DOM_Node& node) const
00360 {
00361 S3FC_DBG( std::cerr << "Node type is: " << node.getNodeType() << std::endl);
00362 switch (node.getNodeType())
00363 {
00364 case DOM_Node::ELEMENT_NODE:
00365 {
00366
00367 S3FC_DBG( std::cerr << "Element: " << node.getNodeName() << std::endl);
00368
00369
00370 DOM_NamedNodeMap attrib = node.getAttributes();
00371
00372 for (int i = 0; i < static_cast<int>(attrib.getLength()); i++)
00373 {
00374 S3FC_DBG( std::cerr << "Attrib: " << attrib.item(i).getNodeName() <<
00375 " = " << attrib.item(i).getNodeValue() << std::endl );
00376 }
00377
00378 break;
00379 }
00380 case DOM_Node::TEXT_NODE:
00381 S3FC_DBG( std::cerr << node.getNodeValue() << std::endl);
00382 break;
00383 default:
00384 D ( std::cerr << "Node type is: " << node.getNodeType() << std::endl );
00385 break;
00386 }
00387
00388 DOM_NodeList child_list = node.getChildNodes();
00389
00390 if (child_list.getLength() > 0)
00391 {
00392 for (int i = 0; i < static_cast<int>(child_list.getLength()); i++)
00393 {
00394 dump_tree(child_list.item(i));
00395 }
00396 }
00397 }
00398 #endif
00399
00400
00401 void s3_xml_config::error_handler::warning(const SAXParseException& e)
00402 {
00403 assemble_and_throw(e, "warning");
00404 }
00405
00406
00407 void s3_xml_config::error_handler::error(const SAXParseException& e)
00408 {
00409 assemble_and_throw(e, "error");
00410 }
00411
00412
00413 void s3_xml_config::error_handler::fatalError(const SAXParseException& e)
00414 {
00415 assemble_and_throw(e, "fatal error");
00416 }
00417
00418
00419 void s3_xml_config::error_handler::resetErrors()
00420 {
00421 return;
00422 }
00423
00424
00425 void s3_xml_config::error_handler::assemble_and_throw(
00426 const SAXParseException& e,
00427 const std::string& type)
00428 {
00429 std::stringstream ss;
00430 ss << "XML Parser reported " << type << ": ";
00431 ss << domstr_to_string(e.getMessage());
00432 ss << " in file ";
00433 if ( e.getSystemId() )
00434 {
00435 ss << "'" << domstr_to_string(e.getSystemId()) << "'";
00436 }
00437 else
00438 {
00439 ss << "<unknown>";
00440 }
00441 ss << " line " << e.getLineNumber() << ", column "
00442 << e.getColumnNumber();
00443 throw s3_xml_exception(ss.str());
00444 }
00445
00446
00447 std::ostream& operator<<(std::ostream& str, const DOMString& s)
00448 {
00449 char* buf = s.transcode();
00450 str << buf;
00451 delete [] buf;
00452 return str;
00453 }