bes  Updated for version 3.20.6
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 
33 #include <DDS.h>
34 #include <DAS.h>
35 #include <DataDDS.h>
36 #include <ConstraintEvaluator.h>
37 // #include <DMR.h>
38 #include <Error.h>
39 
40 #include "BESDapTransmit.h"
41 #include "BESContainer.h"
42 #include "BESDapNames.h"
43 #include "BESDataNames.h"
44 #include "BESResponseNames.h"
45 
46 #include "BESDASResponse.h"
47 #include "BESDDSResponse.h"
48 #include "BESDataDDSResponse.h"
49 
50 #include "BESDMRResponse.h"
51 
52 #include "BESContextManager.h"
53 #include "BESDapError.h"
54 #include "BESInternalFatalError.h"
55 #include "BESDebug.h"
56 
57 #include "BESDapResponseBuilder.h"
58 
59 using namespace libdap;
60 using namespace std;
61 
63 // Local Helpers
64 
65 // File local helper superclass for common exception handling
66 // for transmitting DAP responses.
67 class Sender
68 {
69 public:
70  virtual ~Sender()
71  {
72  }
73 
74  // The main call, non-virtual to force exception handling.
75  // Subclasses will override send_internal private virtual.
76  void send(BESResponseObject* obj, BESDataHandlerInterface & dhi)
77  {
78  string response_string = get_request_type();
79  try {
80  send_internal(obj, dhi);
81  }
82  catch (InternalErr &e) {
83  string err = "libdap error transmitting " + response_string + ": " + e.get_error_message();
84  throw BESDapError(err, true, e.get_error_code(), __FILE__, __LINE__);
85  }
86  catch (Error &e) {
87  string err = "libdap error transmitting " + response_string + ": " + e.get_error_message();
88  throw BESDapError(err, false, e.get_error_code(), __FILE__, __LINE__);
89  }
90  catch (const BESError &e) {
91  throw; // rethrow as is
92  }
93  catch (const std::exception &e) {
94  string msg = "std::exception caught transmitting " + response_string + ": " + e.what()
95  + " (caught in BESDapTransmit).";
96  throw BESInternalFatalError(msg, __FILE__, __LINE__);
97  }
98  catch (...) {
99  string s = "unknown error caught transmitting " + response_string + ": ";
100  BESInternalFatalError ex(s, __FILE__, __LINE__);
101  throw ex;
102  }
103  }
104 
105  // common code for subclasses
106  bool get_print_mime() const
107  {
108  bool found = false;
109  string protocol = BESContextManager::TheManager()->get_context("transmit_protocol", found);
110  bool print_mime = false;
111  if (found && protocol == "HTTP") {
112  print_mime = true;
113  }
114  return print_mime;
115  }
116 
117 private:
118 
119  // Name of the request being sent, for debug
120  virtual string get_request_type() const = 0;
121 
122  // Subclasses impl this for specialized behavior
123  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi) = 0;
124 };
125 
126 class SendDAS: public Sender
127 {
128 private:
129  virtual string get_request_type() const
130  {
131  return "DAS";
132  }
133  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
134  {
135  BESDASResponse *bdas = dynamic_cast<BESDASResponse *>(obj);
136  if (!bdas) {
137  throw BESInternalError("cast error", __FILE__, __LINE__);
138  }
139 
140  DAS *das = bdas->get_das();
141  dhi.first_container();
142  bool print_mime = get_print_mime();
143 
146  rb.send_das(dhi.get_output_stream(), *das, print_mime);
147 
148  //rb.send_das(dhi.get_output_stream(), DDS &dds, ConstraintEvaluator &eval, bool constrained, bool with_mime_headers)
149  }
150 };
151 
152 class SendDDS: public Sender
153 {
154 private:
155  virtual string get_request_type() const
156  {
157  return "DDS";
158  }
159  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
160  {
161  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(obj);
162  if (!bdds) {
163  throw BESInternalError("cast error", __FILE__, __LINE__);
164  }
165 
166  DDS *dds = bdds->get_dds();
167  ConstraintEvaluator & ce = bdds->get_ce();
168 
169  dhi.first_container();
170  bool print_mime = get_print_mime();
171 
174  rb.set_ce(dhi.data[POST_CONSTRAINT]);
175  BESDEBUG("dap", "dhi.data[POST_CONSTRAINT]: " << dhi.data[POST_CONSTRAINT] << endl);
176  rb.send_dds(dhi.get_output_stream(), &dds, ce, true, print_mime);
177  bdds->set_dds(dds);
178  }
179 };
180 
181 class SendDataDDS: public Sender
182 {
183 private:
184  virtual string get_request_type() const
185  {
186  return "DataDDS";
187  }
188  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
189  {
190  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(obj);
191  if (!bdds) {
192  throw BESInternalError("cast error", __FILE__, __LINE__);
193  }
194 
195  DDS *dds = bdds->get_dds();
196  ConstraintEvaluator & ce = bdds->get_ce();
197 
198  dhi.first_container();
199  bool print_mime = get_print_mime();
200 
202  rb.set_dataset_name(dds->filename());
203  rb.set_ce(dhi.data[POST_CONSTRAINT]);
204 
205  rb.set_async_accepted(dhi.data[ASYNC]);
206  rb.set_store_result(dhi.data[STORE_RESULT]);
207 
208  BESDEBUG("dap", "dhi.data[POST_CONSTRAINT]: " << dhi.data[POST_CONSTRAINT] << endl);
209  //rb.send_dap2_data(dhi.get_output_stream(), &dds, ce, print_mime);
210  rb.send_dap2_data(dhi, &dds, ce, print_mime);
211  bdds->set_dds(dds);
212  }
213 };
214 
215 class SendDDX: public Sender
216 {
217 private:
218  virtual string get_request_type() const
219  {
220  return "DDX";
221  }
222  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
223  {
224  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(obj);
225  if (!bdds) {
226  throw BESInternalError("cast error", __FILE__, __LINE__);
227  }
228 
229  DDS *dds = bdds->get_dds();
230  ConstraintEvaluator & ce = bdds->get_ce();
231 
232  dhi.first_container();
233  bool print_mime = get_print_mime();
234 
237  rb.set_ce(dhi.data[POST_CONSTRAINT]);
238  rb.send_ddx(dhi.get_output_stream(), &dds, ce, print_mime);
239  bdds->set_dds(dds);
240  }
241 };
242 
243 class SendDMR: public Sender
244 {
245 private:
246  virtual string get_request_type() const
247  {
248  return "DMR";
249  }
250 
251  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
252  {
253  BESDEBUG("dap", "Entering SendDMR::send_internal ..." << endl);
254 
255  BESDMRResponse *bdmr = dynamic_cast<BESDMRResponse *>(obj);
256  if (!bdmr) throw BESInternalError("cast error", __FILE__, __LINE__);
257 
258  DMR *dmr = bdmr->get_dmr();
259 
260  dhi.first_container();
261 
264 
265  rb.set_dap4ce(dhi.data[DAP4_CONSTRAINT]);
266  rb.set_dap4function(dhi.data[DAP4_FUNCTION]);
267 
268  rb.set_async_accepted(dhi.data[ASYNC]);
269  rb.set_store_result(dhi.data[STORE_RESULT]);
270 
271  rb.send_dmr(dhi.get_output_stream(), *dmr, get_print_mime());
272  }
273 };
274 
275 class SendDap4Data: public Sender
276 {
277 private:
278  virtual string get_request_type() const
279  {
280  return "DAP4Data";
281  }
282  virtual void send_internal(BESResponseObject * obj, BESDataHandlerInterface & dhi)
283  {
284  // In DAP2 we made a special object for data - a child of DDS. That turned to make
285  // some code harder to write, so this time I'll just use the DMR to hold data. jhrg
286  // 10/31/13
287  BESDMRResponse *bdmr = dynamic_cast<BESDMRResponse *>(obj);
288  if (!bdmr) throw BESInternalError("cast error", __FILE__, __LINE__);
289 
290  DMR *dmr = bdmr->get_dmr();
291 
292  dhi.first_container();
293 
295  rb.set_dataset_name(dmr->filename());
296 
297  rb.set_dap4ce(dhi.data[DAP4_CONSTRAINT]);
298  rb.set_dap4function(dhi.data[DAP4_FUNCTION]);
299 
300  rb.set_async_accepted(dhi.data[ASYNC]);
301  rb.set_store_result(dhi.data[STORE_RESULT]);
302 
303  rb.send_dap4_data(dhi.get_output_stream(), *dmr, get_print_mime());
304  }
305 };
306 
308 // Public Interface Impl
309 
310 BESDapTransmit::BESDapTransmit() :
312 {
313  add_method(DAS_SERVICE, BESDapTransmit::send_basic_das);
314  add_method(DDS_SERVICE, BESDapTransmit::send_basic_dds);
315  add_method(DDX_SERVICE, BESDapTransmit::send_basic_ddx);
316  add_method(DATA_SERVICE, BESDapTransmit::send_basic_data);
317 
318  add_method(DMR_SERVICE, BESDapTransmit::send_basic_dmr);
319  add_method(DAP4DATA_SERVICE, BESDapTransmit::send_basic_dap4data);
320 }
321 
322 BESDapTransmit::~BESDapTransmit()
323 {
324  remove_method(DAS_SERVICE);
325  remove_method(DDS_SERVICE);
326  remove_method(DDX_SERVICE);
327  remove_method(DATA_SERVICE);
328 
329  remove_method(DMR_SERVICE);
330  remove_method(DAP4DATA_SERVICE);
331 }
332 
333 void BESDapTransmit::send_basic_das(BESResponseObject * obj, BESDataHandlerInterface & dhi)
334 {
335  SendDAS sender;
336  sender.send(obj, dhi);
337 }
338 
339 void BESDapTransmit::send_basic_dds(BESResponseObject * obj, BESDataHandlerInterface & dhi)
340 {
341  SendDDS sender;
342  sender.send(obj, dhi);
343 }
344 
345 void BESDapTransmit::send_basic_ddx(BESResponseObject * obj, BESDataHandlerInterface & dhi)
346 {
347  SendDDX sender;
348  sender.send(obj, dhi);
349 }
350 
351 void BESDapTransmit::send_basic_data(BESResponseObject * obj, BESDataHandlerInterface & dhi)
352 {
353  SendDataDDS sender;
354  sender.send(obj, dhi);
355 }
356 
357 void BESDapTransmit::send_basic_dmr(BESResponseObject * obj, BESDataHandlerInterface & dhi)
358 {
359  SendDMR sender;
360  sender.send(obj, dhi);
361 }
362 
363 void BESDapTransmit::send_basic_dap4data(BESResponseObject * obj, BESDataHandlerInterface & dhi)
364 {
365  SendDap4Data sender;
366  sender.send(obj, dhi);
367 }
BESDataHandlerInterface::container
BESContainer * container
pointer to current container in this interface
Definition: BESDataHandlerInterface.h:75
BESInternalFatalError
exception thrown if an internal error is found and is fatal to the BES
Definition: BESInternalFatalError.h:43
BESDapResponseBuilder::send_ddx
virtual void send_ddx(std::ostream &out, libdap::DDS **dds, libdap::ConstraintEvaluator &eval, bool with_mime_headers=true)
Definition: BESDapResponseBuilder.cc:1286
BESDataDDSResponse::set_dds
void set_dds(libdap::DDS *ddsIn)
Definition: BESDataDDSResponse.h:73
BESDDSResponse::set_dds
void set_dds(libdap::DDS *ddsIn)
Definition: BESDDSResponse.h:71
BESDDSResponse::get_dds
libdap::DDS * get_dds()
Definition: BESDDSResponse.h:80
BESDASResponse
Represents an OPeNDAP DAS DAP2 data object within the BES.
Definition: BESDASResponse.h:44
BESDapResponseBuilder::send_dds
virtual void send_dds(std::ostream &out, libdap::DDS **dds, libdap::ConstraintEvaluator &eval, bool constrained=false, bool with_mime_headers=true)
Transmit a DDS.
Definition: BESDapResponseBuilder.cc:605
BESDDSResponse::get_ce
libdap::ConstraintEvaluator & get_ce()
Definition: BESDDSResponse.h:92
libdap
Definition: BESDapFunctionResponseCache.h:35
BESDapResponseBuilder::set_dap4function
virtual void set_dap4function(std::string _func)
Definition: BESDapResponseBuilder.cc:216
BESDataHandlerInterface::data
std::map< std::string, std::string > data
the map of string data that will be required for the current request.
Definition: BESDataHandlerInterface.h:90
BESDapResponseBuilder::set_dataset_name
virtual void set_dataset_name(const std::string _dataset)
Set the dataset pathname.
Definition: BESDapResponseBuilder.cc:266
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
BESTransmitter
Definition: BESTransmitter.h:47
BESDDSResponse
Holds a DDS object within the BES.
Definition: BESDDSResponse.h:50
BESDapResponseBuilder::set_ce
virtual void set_ce(std::string _ce)
Definition: BESDapResponseBuilder.cc:169
BESDapResponseBuilder
Definition: BESDapResponseBuilder.h:53
BESDataDDSResponse
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
Definition: BESDataDDSResponse.h:46
BESDapResponseBuilder::set_dap4ce
virtual void set_dap4ce(std::string _ce)
Definition: BESDapResponseBuilder.cc:192
Error
BESContainer::get_real_name
std::string get_real_name() const
retrieve the real name for this container, such as a file name.
Definition: BESContainer.h:180
BESDataHandlerInterface::first_container
void first_container()
set the container pointer to the first container in the containers list
Definition: BESDataHandlerInterface.h:135
BESContextManager::get_context
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
Definition: BESContextManager.cc:77
BESDapError
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:59
BESDataHandlerInterface
Structure storing information used by the BES to handle the request.
Definition: BESDataHandlerInterface.h:56
BESError
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
BESResponseObject
Abstract base class representing a specific set of information in response to a request to the BES.
Definition: BESResponseObject.h:45
BESDMRResponse
Represents an OPeNDAP DMR DAP4 data object within the BES.
Definition: BESDMRResponse.h:39