bes Updated for version 3.20.13
BESDapTransmit.cc
1// BESDapTransmit.cc
2
3// This file is part of bes, A C++ back-end server implementation framework
4// for the OPeNDAP Data Access Protocol.
5
6// Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7// Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22//
23// You can contact University Corporation for Atmospheric Research at
24// 3080 Center Green Drive, Boulder, CO 80301
25
26// (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27// Please read the full copyright statement in the file COPYRIGHT_UCAR.
28//
29// Authors:
30// pwest Patrick West <pwest@ucar.edu>
31// jgarcia Jose Garcia <jgarcia@ucar.edu>
32#include "config.h"
33
34#include <libdap/DDS.h>
35#include <libdap/DAS.h>
36#include <libdap/DataDDS.h>
37#include <libdap/ConstraintEvaluator.h>
38// #include <libdap/DMR.h>
39#include <libdap/Error.h>
40
41#include "BESDapTransmit.h"
42#include "BESContainer.h"
43#include "BESDapNames.h"
44#include "BESDataNames.h"
45#include "BESResponseNames.h"
46
47#include "BESDASResponse.h"
48#include "BESDDSResponse.h"
49#include "BESDataDDSResponse.h"
50
51#include "BESDMRResponse.h"
52
53#include "BESContextManager.h"
54#include "BESDapError.h"
55#include "BESInternalFatalError.h"
56#include "BESDebug.h"
57
58#include "BESDapResponseBuilder.h"
59
60using namespace libdap;
61using namespace std;
62
63#define MODULE "dap"
64#define prolog std::string("DapTransmit::").append(__func__).append("() - ")
65
67// Local Helpers
68
69// File local helper superclass for common exception handling
70// for transmitting DAP responses.
71class Sender
72{
73public:
74 virtual ~Sender()
75 {
76 }
77
78 // The main call, non-virtual to force exception handling.
79 // Subclasses will override send_internal private virtual.
80 void send(BESResponseObject* obj, BESDataHandlerInterface & dhi)
81 {
82 string response_string = get_request_type();
83 try {
84 send_internal(obj, dhi);
85 }
86 catch (InternalErr &e) {
87 string err = "libdap error transmitting " + response_string + ": " + e.get_error_message();
88 throw BESDapError(err, true, e.get_error_code(), __FILE__, __LINE__);
89 }
90 catch (Error &e) {
91 string err = "libdap error transmitting " + response_string + ": " + e.get_error_message();
92 throw BESDapError(err, false, e.get_error_code(), __FILE__, __LINE__);
93 }
94 catch (const BESError &e) {
95 throw; // rethrow as is
96 }
97 catch (const std::exception &e) {
98 string msg = "std::exception caught transmitting " + response_string + ": " + e.what()
99 + " (caught in BESDapTransmit).";
100 throw BESInternalFatalError(msg, __FILE__, __LINE__);
101 }
102 catch (...) {
103 string s = "unknown error caught transmitting " + response_string + ": ";
104 BESInternalFatalError ex(s, __FILE__, __LINE__);
105 throw ex;
106 }
107 }
108
109 // common code for subclasses
110 bool get_print_mime() const
111 {
112 bool found = false;
113 string protocol = BESContextManager::TheManager()->get_context("transmit_protocol", found);
114 bool print_mime = false;
115 if (found && protocol == "HTTP") {
116 print_mime = true;
117 }
118 return print_mime;
119 }
120
121private:
122
123 // Name of the request being sent, for debug
124 virtual string get_request_type() const = 0;
125
126 // Subclasses impl this for specialized behavior
127 virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi) = 0;
128};
129
130class SendDAS: public Sender
131{
132private:
133 virtual string get_request_type() const
134 {
135 return "DAS";
136 }
137 virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
138 {
139 BESDASResponse *bdas = dynamic_cast<BESDASResponse *>(obj);
140 if (!bdas) {
141 throw BESInternalError("cast error", __FILE__, __LINE__);
142 }
143
144 DAS *das = bdas->get_das();
145 dhi.first_container();
146 bool print_mime = get_print_mime();
147
150 rb.send_das(dhi.get_output_stream(), *das, print_mime);
151
152 //rb.send_das(dhi.get_output_stream(), DDS &dds, ConstraintEvaluator &eval, bool constrained, bool with_mime_headers)
153 }
154};
155
156class SendDDS: public Sender
157{
158private:
159 virtual string get_request_type() const
160 {
161 return "DDS";
162 }
163 virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
164 {
165 BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(obj);
166 if (!bdds) {
167 throw BESInternalError("cast error", __FILE__, __LINE__);
168 }
169
170 DDS *dds = bdds->get_dds();
171 ConstraintEvaluator & ce = bdds->get_ce();
172
173 dhi.first_container();
174 bool print_mime = get_print_mime();
175
178 rb.set_ce(dhi.data[POST_CONSTRAINT]);
179 BESDEBUG(MODULE, prolog << "dhi.data[POST_CONSTRAINT]: " << dhi.data[POST_CONSTRAINT] << endl);
180 rb.send_dds(dhi.get_output_stream(), &dds, ce, true, print_mime);
181 bdds->set_dds(dds);
182 }
183};
184
185class SendDataDDS: public Sender
186{
187private:
188 virtual string get_request_type() const
189 {
190 return "DataDDS";
191 }
192 virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
193 {
194 BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(obj);
195 if (!bdds) {
196 throw BESInternalError("cast error", __FILE__, __LINE__);
197 }
198
199 DDS *dds = bdds->get_dds();
200 ConstraintEvaluator & ce = bdds->get_ce();
201
202 dhi.first_container();
203 bool print_mime = get_print_mime();
204
206 rb.set_dataset_name(dds->filename());
207 rb.set_ce(dhi.data[POST_CONSTRAINT]);
208
209 rb.set_async_accepted(dhi.data[ASYNC]);
210 rb.set_store_result(dhi.data[STORE_RESULT]);
211
212 BESDEBUG(MODULE, prolog << "dhi.data[POST_CONSTRAINT]: " << dhi.data[POST_CONSTRAINT] << endl);
213 //rb.send_dap2_data(dhi.get_output_stream(), &dds, ce, print_mime);
214 rb.send_dap2_data(dhi, &dds, ce, print_mime);
215 bdds->set_dds(dds);
216 }
217};
218
219class SendDDX: public Sender
220{
221private:
222 virtual string get_request_type() const
223 {
224 return "DDX";
225 }
226 virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
227 {
228 BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(obj);
229 if (!bdds) {
230 throw BESInternalError("cast error", __FILE__, __LINE__);
231 }
232
233 DDS *dds = bdds->get_dds();
234 ConstraintEvaluator & ce = bdds->get_ce();
235
236 dhi.first_container();
237 bool print_mime = get_print_mime();
238
241 rb.set_ce(dhi.data[POST_CONSTRAINT]);
242 rb.send_ddx(dhi.get_output_stream(), &dds, ce, print_mime);
243 bdds->set_dds(dds);
244 }
245};
246
247class SendDMR: public Sender
248{
249private:
250 virtual string get_request_type() const
251 {
252 return "DMR";
253 }
254
255 virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
256 {
257 BESDEBUG(MODULE, prolog << "SendDMR::send_internal() - BEGIN" << endl);
258
259 BESDMRResponse *bdmr = dynamic_cast<BESDMRResponse *>(obj);
260 if (!bdmr) throw BESInternalError("cast error", __FILE__, __LINE__);
261
262 DMR *dmr = bdmr->get_dmr();
263
264 BESDEBUG(MODULE, prolog << "SendDMR::send_internal() - dmr->request_xml_base(): '"<< dmr->request_xml_base() << endl);
265
266 dhi.first_container();
267
270
271 rb.set_dap4ce(dhi.data[DAP4_CONSTRAINT]);
272 rb.set_dap4function(dhi.data[DAP4_FUNCTION]);
273
274 rb.set_async_accepted(dhi.data[ASYNC]);
275 rb.set_store_result(dhi.data[STORE_RESULT]);
276
277 rb.send_dmr(dhi.get_output_stream(), *dmr, get_print_mime());
278 BESDEBUG(MODULE, prolog << "SendDMR::send_internal() - END" << endl);
279 }
280};
281
282class SendDap4Data: public Sender
283{
284private:
285 virtual string get_request_type() const
286 {
287 return "DAP4Data";
288 }
289 virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
290 {
291 BESDEBUG(MODULE, prolog << "SendDap4Data::send_internal() - BEGIN" << endl);
292 // In DAP2 we made a special object for data - a child of DDS. That turned to make
293 // some code harder to write, so this time I'll just use the DMR to hold data. jhrg
294 // 10/31/13
295 BESDMRResponse *bdmr = dynamic_cast<BESDMRResponse *>(obj);
296 if (!bdmr) throw BESInternalError("cast error", __FILE__, __LINE__);
297
298 DMR *dmr = bdmr->get_dmr();
299
300 BESDEBUG(MODULE, prolog << "SendDap4Data::send_internal() - dmr->request_xml_base(): '"<< dmr->request_xml_base() << endl);
301
302 dhi.first_container();
303
305 rb.set_dataset_name(dmr->filename());
306
307 rb.set_dap4ce(dhi.data[DAP4_CONSTRAINT]);
308 rb.set_dap4function(dhi.data[DAP4_FUNCTION]);
309
310 rb.set_async_accepted(dhi.data[ASYNC]);
311 rb.set_store_result(dhi.data[STORE_RESULT]);
312
313 rb.send_dap4_data(dhi.get_output_stream(), *dmr, get_print_mime());
314 BESDEBUG(MODULE, prolog << "SendDap4Data::send_internal() - END" << endl);
315 }
316};
317
319// Public Interface Impl
320
321BESDapTransmit::BESDapTransmit() :
323{
324 add_method(DAS_SERVICE, BESDapTransmit::send_basic_das);
325 add_method(DDS_SERVICE, BESDapTransmit::send_basic_dds);
326 add_method(DDX_SERVICE, BESDapTransmit::send_basic_ddx);
327 add_method(DATA_SERVICE, BESDapTransmit::send_basic_data);
328
329 add_method(DMR_SERVICE, BESDapTransmit::send_basic_dmr);
330 add_method(DAP4DATA_SERVICE, BESDapTransmit::send_basic_dap4data);
331}
332
333BESDapTransmit::~BESDapTransmit()
334{
335 remove_method(DAS_SERVICE);
336 remove_method(DDS_SERVICE);
337 remove_method(DDX_SERVICE);
338 remove_method(DATA_SERVICE);
339
340 remove_method(DMR_SERVICE);
341 remove_method(DAP4DATA_SERVICE);
342}
343
344void BESDapTransmit::send_basic_das(BESResponseObject * obj, BESDataHandlerInterface & dhi)
345{
346 SendDAS sender;
347 sender.send(obj, dhi);
348}
349
350void BESDapTransmit::send_basic_dds(BESResponseObject * obj, BESDataHandlerInterface & dhi)
351{
352 SendDDS sender;
353 sender.send(obj, dhi);
354}
355
356void BESDapTransmit::send_basic_ddx(BESResponseObject * obj, BESDataHandlerInterface & dhi)
357{
358 SendDDX sender;
359 sender.send(obj, dhi);
360}
361
362void BESDapTransmit::send_basic_data(BESResponseObject * obj, BESDataHandlerInterface & dhi)
363{
364 SendDataDDS sender;
365 sender.send(obj, dhi);
366}
367
368void BESDapTransmit::send_basic_dmr(BESResponseObject * obj, BESDataHandlerInterface & dhi)
369{
370 SendDMR sender;
371 sender.send(obj, dhi);
372}
373
374void BESDapTransmit::send_basic_dap4data(BESResponseObject * obj, BESDataHandlerInterface & dhi)
375{
376 SendDap4Data sender;
377 sender.send(obj, dhi);
378}
std::string get_real_name() const
retrieve the real name for this container, such as a file name.
Definition: BESContainer.h:180
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
Represents an OPeNDAP DAS DAP2 data object within the BES.
Holds a DDS object within the BES.
libdap::ConstraintEvaluator & get_ce()
void set_dds(libdap::DDS *ddsIn)
libdap::DDS * get_dds()
Represents an OPeNDAP DMR DAP4 data object within the BES.
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:59
virtual void set_dataset_name(const std::string _dataset)
Set the dataset pathname.
virtual void set_dap4ce(std::string _ce)
virtual void send_dds(std::ostream &out, libdap::DDS **dds, libdap::ConstraintEvaluator &eval, bool constrained=false, bool with_mime_headers=true)
Transmit a DDS.
virtual void send_ddx(std::ostream &out, libdap::DDS **dds, libdap::ConstraintEvaluator &eval, bool with_mime_headers=true)
virtual void set_dap4function(std::string _func)
virtual void set_ce(std::string _ce)
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
void set_dds(libdap::DDS *ddsIn)
Structure storing information used by the BES to handle the request.
std::map< std::string, std::string > data
the map of string data that will be required for the current request.
void first_container()
set the container pointer to the first container in the containers list
BESContainer * container
pointer to current container in this interface
Base exception class for the BES with basic string message.
Definition: BESError.h:59
exception thrown if internal error encountered
exception thrown if an internal error is found and is fatal to the BES
Abstract base class representing a specific set of information in response to a request to the BES.