2f6160b335447a976ce13b5f631f9b445bc405d9
[metaproxy-moved-to-github.git] / src / filter_zeerex_explain.cpp
1 /* This file is part of Metaproxy.
2    Copyright (C) 2005-2011 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 {
66     m_p->configure(xmlnode);
67 }
68
69 void yf::ZeeRexExplain::process(mp::Package &package) const
70 {
71     m_p->process(package);
72 }
73
74 void yf::ZeeRexExplain::Impl::configure(const xmlNode *confignode)
75 {
76     const xmlNode * dbnode;
77     
78     for (dbnode = confignode->children; dbnode; dbnode = dbnode->next){
79         if (dbnode->type != XML_ELEMENT_NODE)
80             continue;
81         
82         std::string database;
83         mp::xml::check_element_mp(dbnode, "database");
84
85         for (struct _xmlAttr *attr = dbnode->properties; 
86              attr; attr = attr->next){
87             
88             mp::xml::check_attribute(attr, "", "name");
89             database = mp::xml::get_text(attr);
90             
91             std::cout << database << "\n";
92             
93             const xmlNode *explainnode;
94             for (explainnode = dbnode->children; 
95                  explainnode; explainnode = explainnode->next){
96                 if (explainnode->type != XML_ELEMENT_NODE)
97                     continue;
98                 if (explainnode)
99                     break;
100             }
101             // assigning explain node to database name - no check yet 
102             m_database_explain.insert(std::make_pair(database, explainnode));
103          }
104     }
105 }
106
107
108 void yf::ZeeRexExplain::Impl::process(mp::Package &package)
109 {
110     Z_GDU *zgdu_req = package.request().get();
111
112     // ignoring all non HTTP_Request packages
113     if (!zgdu_req || !(zgdu_req->which == Z_GDU_HTTP_Request)){
114         package.move();
115         return;
116     }
117     
118     // only working on  HTTP_Request packages now
119
120     mp::odr odr_de(ODR_DECODE);
121     Z_SRW_PDU *sru_pdu_req = 0;
122
123     mp::odr odr_en(ODR_ENCODE);
124     //Z_SRW_PDU *sru_pdu_res = 0;
125     Z_SRW_PDU *sru_pdu_res = yaz_srw_get(odr_en, Z_SRW_explain_response);
126
127     // finding correct SRU database and explain XML node fragment from config
128     mp_util::SRUServerInfo sruinfo = mp_util::get_sru_server_info(package);
129
130     const xmlNode *explainnode = 0;
131     std::map<std::string, const xmlNode *>::iterator idbexp;
132     idbexp = m_database_explain.find(sruinfo.database);
133
134     //std::cout << "Finding " << sruinfo.database << "\n";
135     if (idbexp != m_database_explain.end()){
136         //std::cout << "Found " << idbexp->first << " " << idbexp->second << "\n";
137         explainnode = idbexp->second;
138     }
139     else {
140         // need to emmit error ?? or just let package pass ??
141         //std::cout << "Missed " << sruinfo.database << "\n";
142         package.move();
143         return;
144     }
145     
146
147     // if SRU package could not be decoded, send minimal explain and
148     // close connection
149
150     Z_SOAP *soap = 0;
151     char *charset = 0;
152     char *stylesheet = 0;
153     if (! (sru_pdu_req = mp_util::decode_sru_request(package, odr_de, odr_en, 
154                                             sru_pdu_res, &soap,
155                                             charset, stylesheet)))
156     {
157         mp_util::build_sru_explain(package, odr_en, sru_pdu_res, 
158                                    sruinfo, explainnode);
159         mp_util::build_sru_response(package, odr_en, soap, 
160                            sru_pdu_res, charset, stylesheet);
161         package.session().close();
162         return;
163     }
164     
165
166     if (sru_pdu_req->which != Z_SRW_explain_request)
167     {
168     // Let pass all other SRU actions
169         package.move();
170         return;
171     }
172     // except valid SRU explain request, construct ZeeRex Explain response
173     else 
174     {
175         Z_SRW_explainRequest *er_req = sru_pdu_req->u.explain_request;
176         //mp_util::build_simple_explain(package, odr_en, sru_pdu_res, 
177         //                           sruinfo, er_req);
178         mp_util::build_sru_explain(package, odr_en, sru_pdu_res, 
179                                    sruinfo, explainnode, er_req);
180         mp_util::build_sru_response(package, odr_en, soap, 
181                                     sru_pdu_res, charset, stylesheet);
182         return;
183     }
184
185     // should never arrive here
186     package.session().close();
187     return;   
188 }
189
190
191
192 static mp::filter::Base* filter_creator()
193 {
194     return new mp::filter::ZeeRexExplain;
195 }
196
197 extern "C" {
198     struct metaproxy_1_filter_struct metaproxy_1_filter_zeerex_explain = {
199         0,
200         "zeerex_explain",
201         filter_creator
202     };
203 }
204
205
206 /*
207  * Local variables:
208  * c-basic-offset: 4
209  * c-file-style: "Stroustrup"
210  * indent-tabs-mode: nil
211  * End:
212  * vim: shiftwidth=4 tabstop=8 expandtab
213  */
214