20 #include <metaproxy/xmlutil.hpp>
30 #include <yaz/xml_include.h>
32 #include <boost/shared_ptr.hpp>
34 #include <libxml/xmlversion.h>
35 #include <libxml/parser.h>
36 #include <libxml/tree.h>
45 std::list<boost::shared_ptr<const mp::filter::Base> >
m_list;
53 const char *file_include_path);
55 typedef std::map<std::string,
56 boost::shared_ptr<const mp::filter::Base > >
61 std::map<std::string,RouterFleXML::Route>
m_routes;
68 const char *file_include_path);
71 bool test_only,
const char *file_include_path);
73 bool test_only,
const char *file_include_path,
76 bool test_only,
const char *file_include_path);
86 virtual const filter::Base *
move(
const char *route);
87 virtual RoutePos *
clone();
89 mp::RouterFleXML::Rep *
m_p;
93 std::list<boost::shared_ptr <const mp::filter::Base> >::iterator
m_filter_it;
97 void mp::RouterFleXML::Rep::parse_xml_filters(xmlDocPtr doc,
100 const char *file_include_path)
102 unsigned int filter_nr = 0;
103 while (node && mp::xml::check_element_mp(node,
"filter"))
107 const struct _xmlAttr *attr;
108 std::string id_value;
109 std::string type_value;
110 for (attr = node->properties; attr; attr = attr->next)
112 std::string name = std::string((
const char *) attr->name);
115 if (attr->children && attr->children->type == XML_TEXT_NODE)
116 value = std::string((
const char *)attr->children->content);
120 else if (name ==
"type")
122 else if (name ==
"base")
125 throw mp::XMLError(
"Only attribute id or type allowed"
126 " in filter element. Got " + name);
129 if (!m_factory->exist(type_value))
131 yaz_log(YLOG_LOG,
"Loading %s (dlpath %s)",
132 type_value.c_str(), m_dl_path.c_str());
133 m_factory->add_creator_dl(type_value, m_dl_path);
135 boost::shared_ptr<mp::filter::Base> fb(m_factory->create(type_value));
137 fb->configure(node, test_only, file_include_path);
139 if (m_id_filter_map.find(id_value) != m_id_filter_map.end())
140 throw mp::XMLError(
"Filter " + id_value +
" already defined");
142 m_id_filter_map[id_value] = fb;
144 node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
148 void mp::RouterFleXML::Rep::parse_xml_filters1(xmlDocPtr doc,
151 const char *file_include_path,
156 if (mp::xml::is_element_mp(node,
"filters"))
158 const xmlNode* node1 =
159 mp::xml::jump_to_children(node, XML_ELEMENT_NODE);
161 parse_xml_filters1(doc, node1, test_only, file_include_path, route);
163 else if (mp::xml::check_element_mp(node,
"filter"))
165 const struct _xmlAttr *attr;
166 std::string refid_value;
167 std::string type_value;
168 for (attr = node->properties; attr; attr = attr->next)
170 std::string name = std::string((
const char *) attr->name);
173 if (attr->children && attr->children->type == XML_TEXT_NODE)
174 value = std::string((
const char *)attr->children->content);
178 else if (name ==
"type")
180 else if (name ==
"base")
183 throw mp::XMLError(
"Only attribute 'refid' or 'type'"
184 " allowed for element 'filter'."
187 if (refid_value.length())
189 std::map<std::string,
190 boost::shared_ptr<const mp::filter::Base > >::iterator it;
191 it = m_id_filter_map.find(refid_value);
192 if (it == m_id_filter_map.end())
193 throw mp::XMLError(
"Unknown filter refid "
196 route.
m_list.push_back(it->second);
198 else if (type_value.length())
200 if (!m_factory->exist(type_value))
202 yaz_log(YLOG_LOG,
"Loading %s (dlpath %s)",
203 type_value.c_str(), m_dl_path.c_str());
204 m_factory->add_creator_dl(type_value, m_dl_path);
206 boost::shared_ptr<mp::filter::Base>
207 filter_base(m_factory->create(type_value));
209 filter_base->configure(node, test_only, file_include_path);
211 route.
m_list.push_back(filter_base);
215 node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
220 void mp::RouterFleXML::Rep::parse_xml_routes(xmlDocPtr doc,
223 const char *file_include_path)
225 mp::xml::check_element_mp(node,
"route");
227 unsigned int route_nr = 0;
228 while (mp::xml::is_element_mp(node,
"route"))
232 const struct _xmlAttr *attr;
233 std::string id_value;
234 for (attr = node->properties; attr; attr = attr->next)
236 std::string name = std::string((
const char *) attr->name);
239 if (attr->children && attr->children->type == XML_TEXT_NODE)
240 value = std::string((
const char *)attr->children->content);
244 else if (name ==
"base")
247 throw mp::XMLError(
"Only attribute 'id' allowed for"
255 const xmlNode* node3 = mp::xml::jump_to_children(node, XML_ELEMENT_NODE);
259 parse_xml_filters1(doc, node3, test_only, file_include_path, route);
261 std::map<std::string,RouterFleXML::Route>::iterator it;
262 it = m_routes.find(id_value);
263 if (it != m_routes.end())
264 throw mp::XMLError(
"Route id='" + id_value
265 +
"' already exist");
267 m_routes[id_value] = route;
268 node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
272 void mp::RouterFleXML::Rep::check_routes_in_filters(
const xmlNode *node)
276 if (mp::xml::is_element_mp(node,
"filters"))
279 mp::xml::jump_to_children(node, XML_ELEMENT_NODE);
280 check_routes_in_filters(n);
282 else if (mp::xml::is_element_mp(node,
"filter"))
285 mp::xml::jump_to_children(node, XML_ELEMENT_NODE);
288 const struct _xmlAttr *attr;
291 for (attr = n->properties; attr; attr = attr->next)
293 if (!strcmp((
const char *) attr->name,
"route"))
297 if (attr->children && attr->children->type == XML_TEXT_NODE)
298 value = std::string((
const char *)attr->children->content);
300 std::map<std::string,RouterFleXML::Route>::iterator it;
301 it = m_routes.find(value);
302 if (it == m_routes.end())
304 throw mp::XMLError(
"Route '" + value +
"' does not exist");
308 n = mp::xml::jump_to_next(n, XML_ELEMENT_NODE);
311 node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
315 void mp::RouterFleXML::Rep::parse_xml_config_dom(xmlDocPtr doc,
317 const char *file_include_path)
320 throw mp::XMLError(
"Empty XML Document");
322 const xmlNode* root = xmlDocGetRootElement(doc);
324 if (file_include_path)
326 int r = yaz_xml_include_glob((xmlNode *) root, file_include_path,
327 YAZ_FILE_GLOB_FAIL_NOTEXIST);
329 throw mp::XMLError(
"YAZ XML Include failed");
332 mp::xml::check_element_mp(root,
"metaproxy");
334 const xmlNode* node = mp::xml::jump_to_children(root, XML_ELEMENT_NODE);
336 if (mp::xml::is_element_mp(node,
"dlpath"))
338 m_dl_path = mp::xml::get_text(node);
339 node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
342 if (mp::xml::check_element_mp(node,
"start"))
344 const struct _xmlAttr *attr;
345 for (attr = node->properties; attr; attr = attr->next)
347 std::string name = std::string((
const char *) attr->name);
350 if (attr->children && attr->children->type == XML_TEXT_NODE)
351 value = std::string((
const char *)attr->children->content);
354 m_start_route = value;
355 else if (name ==
"base")
358 throw mp::XMLError(
"Only attribute route allowed"
359 " in element 'start'. Got " + name);
361 node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
364 if (mp::xml::is_element_mp(node,
"filters"))
366 parse_xml_filters(doc, mp::xml::jump_to_children(node,
368 test_only, file_include_path);
370 node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
373 mp::xml::check_element_mp(node,
"routes");
375 parse_xml_routes(doc, mp::xml::jump_to_children(node, XML_ELEMENT_NODE),
376 test_only, file_include_path);
378 node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
381 throw mp::XMLError(
"Unexpected element "
382 + std::string((
const char *)node->name));
385 node = mp::xml::jump_to_children(root, XML_ELEMENT_NODE);
388 if (mp::xml::is_element_mp(node,
"filters"))
389 check_routes_in_filters(
390 mp::xml::jump_to_children(node,
392 else if (mp::xml::is_element_mp(node,
"routes"))
394 const xmlNode* n = mp::xml::jump_to_children(node,
398 if (mp::xml::is_element_mp(n,
"route"))
400 check_routes_in_filters(
401 mp::xml::jump_to_children(n, XML_ELEMENT_NODE));
404 n = mp::xml::jump_to_next(n, XML_ELEMENT_NODE);
407 node = mp::xml::jump_to_next(node, XML_ELEMENT_NODE);
409 std::map<std::string,RouterFleXML::Route>::iterator it;
410 it = m_routes.find(m_start_route);
411 if (it == m_routes.end())
412 throw mp::XMLError(
"Start route '" + m_start_route +
"' not found");
415 mp::RouterFleXML::Rep::Rep() : m_xinclude(false)
420 bool test_only,
const char *file_include_path)
422 m_factory = &factory;
423 m_start_route =
"start";
424 parse_xml_config_dom(doc, test_only, file_include_path);
428 bool test_only,
const char *file_include_path)
431 m_p->base(doc, factory, test_only, file_include_path);
438 xmlDocPtr doc = xmlParseMemory(xmlconf.c_str(),
441 throw mp::XMLError(
"xmlParseMemory failed");
444 m_p->base(doc, factory, test_only, 0);
453 const mp::filter::Base *mp::RouterFleXML::Pos::move(
const char *route)
457 m_route_it = m_p->m_routes.find(route);
458 if (m_route_it == m_p->m_routes.end())
460 yaz_log(YLOG_FATAL,
"no such route %s", route);
463 m_filter_it = m_route_it->second.m_list.begin();
465 if (m_filter_it == m_route_it->second.m_list.end())
467 const mp::filter::Base *f = (*m_filter_it).get();
474 mp::RouterFleXML::Pos *p =
new mp::RouterFleXML::Pos;
476 p->m_route_it = m_p->m_routes.find(m_p->m_start_route);
477 if (p->m_route_it == m_p->m_routes.end())
482 p->m_filter_it = p->m_route_it->second.m_list.begin();
487 mp::RoutePos *mp::RouterFleXML::Pos::clone()
489 mp::RouterFleXML::Pos *p =
new mp::RouterFleXML::Pos;
490 p->m_filter_it = m_filter_it;
491 p->m_route_it = m_route_it;
496 mp::RouterFleXML::Pos::~Pos()
503 std::map<std::string,RouterFleXML::Route>::iterator route_it;
505 route_it = m_p->m_routes.begin();
506 while (route_it != m_p->m_routes.end())
510 std::list<boost::shared_ptr<const mp::filter::Base> >::iterator it;
512 for (it = route.
m_list.begin(); it != route.
m_list.end(); it++)
520 std::map<std::string,RouterFleXML::Route>::iterator route_it;
522 route_it = m_p->m_routes.begin();
523 while (route_it != m_p->m_routes.end())
527 std::list<boost::shared_ptr<const mp::filter::Base> >::iterator it;
529 for (it = route.
m_list.begin(); it != route.
m_list.end(); it++)