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