bes  Updated for version 3.20.8
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 <DDS.h>
35 #include <DAS.h>
36 #include <DataDDS.h>
37 #include <ConstraintEvaluator.h>
38 // #include <DMR.h>
39 #include <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 
60 using namespace libdap;
61 using 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.
71 class Sender
72 {
73 public:
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 
121 private:
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 
130 class SendDAS: public Sender
131 {
132 private:
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 
156 class SendDDS: public Sender
157 {
158 private:
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 
185 class SendDataDDS: public Sender
186 {
187 private:
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 
219 class SendDDX: public Sender
220 {
221 private:
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 
247 class SendDMR: public Sender
248 {
249 private:
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 
282 class SendDap4Data: public Sender
283 {
284 private:
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 
321 BESDapTransmit::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 
333 BESDapTransmit::~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 
344 void BESDapTransmit::send_basic_das(BESResponseObject * obj, BESDataHandlerInterface & dhi)
345 {
346  SendDAS sender;
347  sender.send(obj, dhi);
348 }
349 
350 void BESDapTransmit::send_basic_dds(BESResponseObject * obj, BESDataHandlerInterface & dhi)
351 {
352  SendDDS sender;
353  sender.send(obj, dhi);
354 }
355 
356 void BESDapTransmit::send_basic_ddx(BESResponseObject * obj, BESDataHandlerInterface & dhi)
357 {
358  SendDDX sender;
359  sender.send(obj, dhi);
360 }
361 
362 void BESDapTransmit::send_basic_data(BESResponseObject * obj, BESDataHandlerInterface & dhi)
363 {
364  SendDataDDS sender;
365  sender.send(obj, dhi);
366 }
367 
368 void BESDapTransmit::send_basic_dmr(BESResponseObject * obj, BESDataHandlerInterface & dhi)
369 {
370  SendDMR sender;
371  sender.send(obj, dhi);
372 }
373 
374 void 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.
void set_dds(libdap::DDS *ddsIn)
libdap::ConstraintEvaluator & get_ce()
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
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
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.