Windows: use Boost 1.59, msvc 14.0
[metaproxy-moved-to-github.git] / src / filter_zeerex_explain.cpp
1 /* This file is part of Metaproxy.
2    Copyright (C) Index Data
3
4 Metaproxy is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18
19 #include "config.hpp"
20 #include "filter_zeerex_explain.hpp"
21 #include <metaproxy/package.hpp>
22 #include <metaproxy/util.hpp>
23 #include "gduutil.hpp"
24 #include "sru_util.hpp"
25
26 #include <yaz/zgdu.h>
27 #include <yaz/z-core.h>
28 #include <yaz/srw.h>
29 #include <yaz/pquery.h>
30
31 #include <boost/thread/mutex.hpp>
32
33 #include <iostream>
34 #include <sstream>
35 #include <string>
36 #include <algorithm>
37 #include <map>
38
39 namespace mp = metaproxy_1;
40 namespace mp_util = metaproxy_1::util;
41 namespace yf = mp::filter;
42
43
44 namespace metaproxy_1 {
45     namespace filter {
46         class ZeeRexExplain::Impl {
47         public:
48             void configure(const xmlNode *xmlnode);
49             void process(metaproxy_1::Package &package);
50         private:
51             std::map<std::string, const xmlNode *> m_database_explain;
52         };
53     }
54 }
55
56 yf::ZeeRexExplain::ZeeRexExplain() : m_p(new Impl)
57 {
58 }
59
60 yf::ZeeRexExplain::~ZeeRexExplain()
61 {  // must have a destructor because of boost::scoped_ptr
62 }
63
64 void yf::ZeeRexExplain::configure(const xmlNode *xmlnode, bool test_only,
65                                   const char *path)
66 {
67     m_p->configure(xmlnode);
68 }
69
70 void yf::ZeeRexExplain::process(mp::Package &package) const
71 {
72     m_p->process(package);
73 }
74
75 void yf::ZeeRexExplain::Impl::configure(const xmlNode *confignode)
76 {
77     const xmlNode * dbnode;
78
79     for (dbnode = confignode->children; dbnode; dbnode = dbnode->next){
80         if (dbnode->type != XML_ELEMENT_NODE)
81             continue;
82
83         std::string database;
84         mp::xml::check_element_mp(dbnode, "database");
85
86         for (struct _xmlAttr *attr = dbnode->properties;
87              attr; attr = attr->next){
88
89             mp::xml::check_attribute(attr, "", "name");
90             database = mp::xml::get_text(attr);
91
92             std::cout << database << "\n";
93
94             const xmlNode *explainnode;
95             for (explainnode = dbnode->children;
96                  explainnode; explainnode = explainnode->next){
97                 if (explainnode->type != XML_ELEMENT_NODE)
98                     continue;
99                 if (explainnode)
100                     break;
101             }
102             // assigning explain node to database name - no check yet
103             m_database_explain.insert(std::make_pair(database, explainnode));
104          }
105     }
106 }
107
108
109 void yf::ZeeRexExplain::Impl::process(mp::Package &package)
110 {
111     Z_GDU *zgdu_req = package.request().get();
112
113     // ignoring all non HTTP_Request packages
114     if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)){
115         package.move();
116         return;
117     }
118
119     // only working on  HTTP_Request packages now
120
121     mp::odr odr_de(ODR_DECODE);
122     Z_SRW_PDU *sru_pdu_req = 0;
123
124     mp::odr odr_en(ODR_ENCODE);
125     //Z_SRW_PDU *sru_pdu_res = 0;
126     Z_SRW_PDU *sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_explain_response);
127
128     // finding correct SRU database and explain XML node fragment from config
129     mp_util::SRUServerInfo sruinfo = mp_util::get_sru_server_info(package);
130
131     const xmlNode *explainnode = 0;
132     std::map<std::string, const xmlNode *>::iterator idbexp;
133     idbexp = m_database_explain.find(sruinfo.database);
134
135     //std::cout << "Finding " << sruinfo.database << "\n";
136     if (idbexp != m_database_explain.end()){
137         //std::cout << "Found " << idbexp->first << " " << idbexp->second << "\n";
138         explainnode = idbexp->second;
139     }
140     else {
141         // need to emmit error ?? or just let package pass ??
142         //std::cout << "Missed " << sruinfo.database << "\n";
143         package.move();
144         return;
145     }
146
147
148     // if SRU package could not be decoded, send minimal explain and
149     // close connection
150
151     Z_SOAP *soap = 0;
152     char *charset = 0;
153     char *stylesheet = 0;
154     Z_SRW_diagnostic *diagnostic = 0;
155     int num_diagnostic = 0;
156
157     if (! (sru_pdu_req = mp_util::decode_sru_request(
158                package, odr_de, odr_en,
159                &diagnostic, &num_diagnostic, &soap,
160                charset)))
161     {
162         mp_util::build_sru_explain(package, odr_en, sru_pdu_res,
163                                    sruinfo, explainnode);
164         mp_util::build_sru_response(package, odr_en, soap,
165                            sru_pdu_res, charset, stylesheet);
166         package.session().close();
167         return;
168     }
169
170
171     if (sru_pdu_req->which != Z_SRW_explain_request)
172     {
173     // Let pass all other SRU actions
174         package.move();
175         return;
176     }
177     // except valid SRU explain request, construct ZeeRex Explain response
178     else
179     {
180         Z_SRW_explainRequest *er_req = sru_pdu_req->u.explain_request;
181
182         sru_pdu_res->u.explain_response->diagnostics = diagnostic;
183         sru_pdu_res->u.explain_response->num_diagnostics = num_diagnostic;
184         //mp_util::build_simple_explain(package, odr_en, sru_pdu_res,
185         //                           sruinfo, er_req);
186         mp_util::build_sru_explain(package, odr_en, sru_pdu_res,
187                                    sruinfo, explainnode, er_req);
188         mp_util::build_sru_response(package, odr_en, soap,
189                                     sru_pdu_res, charset, stylesheet);
190         return;
191     }
192
193     // should never arrive here
194     package.session().close();
195     return;
196 }
197
198
199
200 static mp::filter::Base* filter_creator()
201 {
202     return new mp::filter::ZeeRexExplain;
203 }
204
205 extern "C" {
206     struct metaproxy_1_filter_struct metaproxy_1_filter_zeerex_explain = {
207         0,
208         "zeerex_explain",
209         filter_creator
210     };
211 }
212
213
214 /*
215  * Local variables:
216  * c-basic-offset: 4
217  * c-file-style: "Stroustrup"
218  * indent-tabs-mode: nil
219  * End:
220  * vim: shiftwidth=4 tabstop=8 expandtab
221  */
222