7ec4ba427a67379bf84af37d046b7fe442ac9ba9
[metaproxy-moved-to-github.git] / src / ex_libxml2_conf.cpp
1 /* $Id: ex_libxml2_conf.cpp,v 1.4 2005-10-26 10:20:15 marc Exp $
2    Copyright (c) 2005, Index Data.
3
4 %LICENSE%
5  */
6
7 #include <iostream>
8 #include <stdexcept>
9
10 #include <boost/program_options.hpp>
11 namespace po = boost::program_options;
12
13 #include <libxml/xmlreader.h>
14
15 class Configuration 
16 {
17 public:
18     Configuration(int argc, char **argv)
19         {            
20             m_config = "";
21             m_duration = 0;
22             m_xinclude = false;
23             m_xml_conf_doc = 0;
24    
25             parse_command_line(argc, argv);
26             parse_xml_config();
27         }
28     
29 public:
30     std::string config()
31         {
32          return m_config;
33         }
34     int duration()
35         {
36             return m_duration;
37         }
38     
39     
40 private:
41     std::string m_config;
42     int m_duration;      
43     bool m_xinclude;
44     xmlDoc * m_xml_conf_doc;
45     
46     
47     void parse_command_line(int argc, char **argv)
48         {
49             po::options_description generic("Generic options");
50             generic.add_options()
51                 ("help,h", "produce help message")
52                 ("version,v", "version number")
53                 ("xinclude,x", "allow Xinclude on XML config files")
54                 ;
55             
56             po::options_description config("Configuration options");
57          config.add_options()
58             ("config,c", po::value<std::string>(&m_config)->default_value("../etc/config1.xml"),
59              "config XML file path (string)")
60             ("duration,d", po::value<int>(&m_duration)->default_value(0),
61              "number of seconds for server to exist (int)")
62             //("commands", po::value< std::vector<std::string> >(), 
63             //  "listener ports (string)")
64             ;
65          
66          //po::positional_options_description p;
67          // p.add("port", -1);
68          
69          po::options_description cmdline_options;
70          cmdline_options.add(generic).add(config);
71          po::variables_map vm;        
72
73          try 
74          {
75             //po::store(po::command_line_parser(argc, argv).
76             //       options(cmdline_options).positional(p).run(), vm);
77             //po::store(po::command_line_parser(argc, argv).
78             //     options(cmdline_options).run(), vm);
79             po::store(po::parse_command_line(argc, argv,  cmdline_options), vm);
80             po::notify(vm);    
81          }
82          catch ( po::invalid_command_line_syntax &e) {      
83             std::cerr << "ex_libxml2_conf error: " << e.what() << std::endl;
84             std::cerr << generic << config << std::endl;
85             std::exit(1);
86         }
87          catch ( po::invalid_option_value &e) {      
88             //std::cerr << "ex_libxml2_conf error: " << e.what() << std::endl;
89             std::cerr << "invalid option value" << std::endl;
90             std::cerr << generic << config << std::endl;
91             std::exit(1);
92          }
93          catch ( po::unknown_option &e) {      
94             std::cerr << "ex_libxml2_conf error: " << e.what() << std::endl;
95             std::cerr << generic << config << std::endl;
96            std::exit(1);
97          }
98          
99          std::cout << "ex_libxml2_conf ";
100          
101          if (vm.count("help")) {
102             std::cout << "--help" << std::endl;
103             std::cout << generic << config << std::endl;
104             std::exit(0);
105          }
106          
107         if (vm.count("version")) {
108            std::cout << "--version" << std::endl;
109            std::exit(0);
110         }
111          
112         if (vm.count("xinclude")) {
113            std::cout << "--xinclude" << std::endl;
114            m_xinclude = true;
115         }
116         
117         if (vm.count("duration")) {
118            std::cout << "--duration " 
119                      << vm["duration"].as<int>() << " ";
120         }
121         if (vm.count("config")) {
122            std::cout << "--config " 
123                      << vm["config"].as<std::string>() << " ";
124         }
125         
126         std::cout << std::endl;
127
128         //if (vm.count("port"))
129         //{
130         //    std::vector<std::string> ports = 
131         //       vm["port"].as< std::vector<std::string> >();
132         //    
133         //    for (size_t i = 0; i<ports.size(); i++)
134         //       std::cout << "port " << i << " " << ports[i] << std::endl;
135             
136         //}
137
138         }
139     
140     void parse_xml_config() {   
141         LIBXML_TEST_VERSION
142
143         xmlTextReader* reader;
144         //reader->SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1);
145         int ret;
146         reader = xmlReaderForFile(m_config.c_str(), NULL, 0);
147  
148         if (reader == NULL) {
149             std::cerr << "failed to open XML config file " 
150                       << m_config << std::endl;
151             std::exit(1);
152         }
153
154
155         // root element processing
156         xml_progress_deep_to_element(reader);
157         if (std::string("yp2") != (const char*)xmlTextReaderConstName(reader))
158             xml_error(reader, "root element must be named <yp2>");
159
160         std::cout << "<" << xmlTextReaderConstName(reader);
161
162         //if (xmlTextReaderHasAttributes(reader))
163         //if ((!xmlTextReaderMoveToAttributeNs(reader, NULL,
164         //                         (const xmlChar*)"http://indexdata.dk/yp2/config/1" )))
165         if ((!xmlTextReaderMoveToFirstAttribute(reader))
166           || (! xmlTextReaderIsNamespaceDecl(reader))
167           || (std::string("http://indexdata.dk/yp2/config/1") 
168               != (const char*)xmlTextReaderConstValue(reader)))
169             xml_error(reader, "expected root element <yp2> in namespace "
170                       "'http://indexdata.dk/yp2/config/1'");
171
172         std::cout << " " << xmlTextReaderConstName(reader) << "=\""  
173                   << xmlTextReaderConstValue(reader) << "\">"  
174             //<< xmlTextReaderIsNamespaceDecl(reader)
175                   << std::endl;
176
177
178         // start element processing
179         xml_progress_deep_to_element(reader);
180         if (std::string("start") != (const char*)xmlTextReaderConstName(reader)
181             || !xmlTextReaderMoveToFirstAttribute(reader)
182             || std::string("route") != (const char*)xmlTextReaderConstName(reader)
183             )
184             xml_error(reader, "start element <start route=\"route_id\"/> expected");
185
186         std::cout << "<start " << xmlTextReaderConstName(reader) <<  "=\"" 
187                   <<  xmlTextReaderConstValue(reader) << "\"/>" << std::endl;
188              //<< xmlTextReaderGetAttribute(reader, (const xmlChar *)"route") 
189
190
191         // filters element processing
192         xml_progress_flat_to_element(reader);
193         if (std::string("filters") != (const char*)xmlTextReaderConstName(reader)
194             )
195             xml_error(reader, "filters element <filters> expected");
196
197         std::cout << "<filters>" << std::endl;
198                   
199
200         // filter element processing
201         xml_progress_deep_to_element(reader);
202         if (std::string("filter") != (const char*)xmlTextReaderConstName(reader)
203             )
204             xml_error(reader, "filter element <filter id=\"some_id\" "
205                       "type=\"some_type\"/> expected");
206
207         while (std::string("filter") == (const char*)xmlTextReaderConstName(reader)){
208             std::string filter_id;
209             std::string filter_type;
210             if (!xmlTextReaderMoveToFirstAttribute(reader)
211                 || std::string("id") != (const char*)xmlTextReaderConstName(reader))
212                 xml_error(reader, "filter element <filter id=\"some_id\" "
213                           "type=\"some_type\"/> expected");
214             filter_id = (const char*)xmlTextReaderConstValue(reader);
215             if (!xmlTextReaderMoveToNextAttribute(reader)
216                 || std::string("type") != (const char*)xmlTextReaderConstName(reader))
217                 xml_error(reader, "filter element <filter id=\"some_id\" "
218                           "type=\"some_type\"/> expected");
219             filter_type = (const char*)xmlTextReaderConstValue(reader);
220             std::cout << "<filter id=\"" << filter_id 
221                       << "\" type=\"" << filter_type << "\"/>" 
222                       << std::endl;
223             xml_progress_flat_to_element(reader);
224         }
225
226         std::cout << "</filters>" << std::endl;
227
228
229         // routes element processing
230         // xml_progress_flat_to_element(reader);
231         if (std::string("routes") != (const char*)xmlTextReaderConstName(reader)
232             )
233             xml_error(reader, "routes element <routes> expected");
234
235         std::cout << "<routes>" << std::endl;
236         // route element processing
237         xml_progress_deep_to_element(reader);
238         if (std::string("route") != (const char*)xmlTextReaderConstName(reader)
239             )
240             xml_error(reader, "route element <route id=\"some_id\" "
241                       "type=\"some_type\"/> expected");
242         while (std::string("route") == (const char*)xmlTextReaderConstName(reader)){
243             std::string route_id;
244             if (!xmlTextReaderMoveToFirstAttribute(reader)
245                 || std::string("id") != (const char*)xmlTextReaderConstName(reader))
246                 xml_error(reader, "route element <route id=\"some_id\"/> expected");
247             route_id = (const char*)xmlTextReaderConstValue(reader);
248
249
250             std::cout << "<route id=\"" << route_id << "\">" << std::endl;
251             std::cout << "</route>" << std::endl;
252             xml_progress_flat_to_element(reader);
253         }
254
255         std::cout << "</routes>" << std::endl;
256
257         std::cout << "</yp2>" << std::endl;
258
259
260         xml_debug_print(reader);
261         
262
263         // freeing C xml reader libs
264         xmlFreeTextReader(reader);
265         if (ret != 0) {
266             std::cerr << "Parsing failed of XML config file " 
267                       << m_config << std::endl;
268             std::exit(1);
269         }
270     }
271
272     void xml_error ( xmlTextReader* reader, std::string msg)
273         {
274             std::cerr << "ERROR: " << msg << " "
275                       << xmlTextReaderGetParserLineNumber(reader) << ":" 
276                       << xmlTextReaderGetParserColumnNumber(reader) << " " 
277                       << xmlTextReaderConstName(reader) << " "  
278                       << xmlTextReaderDepth(reader) << " " 
279                       << xmlTextReaderNodeType(reader) << std::endl;
280         }
281     
282     void xml_debug_print ( xmlTextReader* reader)
283         {
284         // processing all other elements
285         //while (xmlTextReaderMoveToElement(reader)) // reads next element ??
286         //while (xmlTextReaderNext(reader)) //does not descend, keeps level 
287         while (xmlTextReaderRead(reader)) // descends into all subtree nodes
288             std::cout << xmlTextReaderGetParserLineNumber(reader) << ":" 
289                       << xmlTextReaderGetParserColumnNumber(reader) << " " 
290                       << xmlTextReaderDepth(reader) << " " 
291                       << xmlTextReaderNodeType(reader) << " "
292                       << "ConstName " << xmlTextReaderConstName(reader) << " "  
293                 //<< "Prefix " << xmlTextReaderPrefix(reader) << "\n"  
294                 //<< "XmlLang " << xmlTextReaderXmlLang(reader) << "\n"  
295                 //<< "NamespaceUri " << xmlTextReaderNamespaceUri(reader) << "\n"  
296                 //<< "BaseUri"  << xmlTextReaderBaseUri(reader) << "\n"  
297                       << std::endl;
298         }
299     
300     bool xml_progress_deep_to_element(xmlTextReader* reader)
301         {
302             bool ret = false;
303             while(xmlTextReaderRead(reader) 
304                   && xmlTextReaderNodeType(reader) !=  XML_ELEMENT_NODE
305                   && !( xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT
306                         && 0 == xmlTextReaderDepth(reader))
307                 ) 
308                 ret = true;
309             return ret;
310         }
311     
312     bool xml_progress_flat_to_element(xmlTextReader* reader)
313         {
314             bool ret = false;
315             
316             while(xmlTextReaderNext(reader) 
317                   && xmlTextReaderNodeType(reader) != XML_ELEMENT_NODE
318                   && !( xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT
319                         && 0 == xmlTextReaderDepth(reader))
320                 ) {    
321                 ret = true;
322             }
323             return ret;
324         }
325     
326
327 };
328
329
330
331 int main(int argc, char **argv)
332 {
333    //try 
334    //{
335
336    
337    Configuration conf(argc, argv);
338
339    std::cout << "config " << conf.config() << std::endl;
340    std::cout << "duration " << conf.duration() << std::endl;
341    
342
343
344
345         // }
346         //catch ( ... ) {
347         //std::cerr << "Unknown Exception" << std::endl;
348         //throw();
349         //std::exit(1);
350         //}
351    std::exit(0);
352 }
353
354
355
356
357 /*
358  * Local variables:
359  * c-basic-offset: 4
360  * indent-tabs-mode: nil
361  * c-file-style: "stroustrup"
362  * End:
363  * vim: shiftwidth=4 tabstop=8 expandtab
364  */